diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 702f2c867..b2d5eabd0 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -148,6 +148,7 @@ SET(repositories repositories/base/base_character_currency_repository.h repositories/base/base_character_data_repository.h repositories/base/base_character_disciplines_repository.h + repositories/base/base_character_expedition_lockouts_repository.h repositories/base/base_character_inspect_messages_repository.h repositories/base/base_character_item_recast_repository.h repositories/base/base_character_languages_repository.h @@ -166,11 +167,16 @@ SET(repositories repositories/base/base_char_recipe_list_repository.h repositories/base/base_completed_tasks_repository.h repositories/base/base_content_flags_repository.h + repositories/base/base_damageshieldtypes_repository.h repositories/base/base_data_buckets_repository.h repositories/base/base_db_str_repository.h repositories/base/base_discovered_items_repository.h repositories/base/base_doors_repository.h + repositories/base/base_dynamic_zones_repository.h repositories/base/base_eventlog_repository.h + repositories/base/base_expeditions_repository.h + repositories/base/base_expedition_lockouts_repository.h + repositories/base/base_expedition_members_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 @@ -267,7 +273,6 @@ SET(repositories repositories/base/base_traps_repository.h repositories/base/base_tributes_repository.h repositories/base/base_tribute_levels_repository.h - repositories/base/base_variables_repository.h repositories/base/base_veteran_reward_templates_repository.h repositories/base/base_zone_repository.h repositories/base/base_zone_points_repository.h @@ -306,6 +311,7 @@ SET(repositories repositories/character_currency_repository.h repositories/character_data_repository.h repositories/character_disciplines_repository.h + repositories/character_expedition_lockouts_repository.h repositories/character_inspect_messages_repository.h repositories/character_item_recast_repository.h repositories/character_languages_repository.h @@ -324,11 +330,16 @@ SET(repositories repositories/char_recipe_list_repository.h repositories/completed_tasks_repository.h repositories/content_flags_repository.h + repositories/damageshieldtypes_repository.h repositories/data_buckets_repository.h repositories/db_str_repository.h repositories/discovered_items_repository.h repositories/doors_repository.h + repositories/dynamic_zones_repository.h repositories/eventlog_repository.h + repositories/expeditions_repository.h + repositories/expedition_lockouts_repository.h + repositories/expedition_members_repository.h repositories/faction_base_data_repository.h repositories/faction_list_repository.h repositories/faction_list_mod_repository.h @@ -425,7 +436,6 @@ SET(repositories repositories/traps_repository.h repositories/tributes_repository.h repositories/tribute_levels_repository.h - repositories/variables_repository.h repositories/veteran_reward_templates_repository.h repositories/zone_repository.h repositories/zone_points_repository.h diff --git a/common/repositories/base/base_aa_ability_repository.h b/common/repositories/base/base_aa_ability_repository.h index 965d8d9b9..f687604b1 100644 --- a/common/repositories/base/base_aa_ability_repository.h +++ b/common/repositories/base/base_aa_ability_repository.h @@ -269,7 +269,7 @@ public: insert_values.push_back(std::to_string(aa_ability_entry.enabled)); insert_values.push_back(std::to_string(aa_ability_entry.reset_on_death)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_aa_rank_effects_repository.h b/common/repositories/base/base_aa_rank_effects_repository.h index 3d8341f3b..4bed89085 100644 --- a/common/repositories/base/base_aa_rank_effects_repository.h +++ b/common/repositories/base/base_aa_rank_effects_repository.h @@ -215,7 +215,7 @@ public: insert_values.push_back(std::to_string(aa_rank_effects_entry.base1)); insert_values.push_back(std::to_string(aa_rank_effects_entry.base2)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_aa_rank_prereqs_repository.h b/common/repositories/base/base_aa_rank_prereqs_repository.h index ca1441e21..5bd751938 100644 --- a/common/repositories/base/base_aa_rank_prereqs_repository.h +++ b/common/repositories/base/base_aa_rank_prereqs_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(aa_rank_prereqs_entry.aa_id)); insert_values.push_back(std::to_string(aa_rank_prereqs_entry.points)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_aa_ranks_repository.h b/common/repositories/base/base_aa_ranks_repository.h index 6f986c14d..87af9d210 100644 --- a/common/repositories/base/base_aa_ranks_repository.h +++ b/common/repositories/base/base_aa_ranks_repository.h @@ -263,7 +263,7 @@ public: insert_values.push_back(std::to_string(aa_ranks_entry.prev_id)); insert_values.push_back(std::to_string(aa_ranks_entry.next_id)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_account_flags_repository.h b/common/repositories/base/base_account_flags_repository.h index 7c9dda34e..17c135219 100644 --- a/common/repositories/base/base_account_flags_repository.h +++ b/common/repositories/base/base_account_flags_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back("'" + EscapeString(account_flags_entry.p_flag) + "'"); insert_values.push_back("'" + EscapeString(account_flags_entry.p_value) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_account_ip_repository.h b/common/repositories/base/base_account_ip_repository.h index 393f03e69..757e72ef6 100644 --- a/common/repositories/base/base_account_ip_repository.h +++ b/common/repositories/base/base_account_ip_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(account_ip_entry.count)); insert_values.push_back("'" + EscapeString(account_ip_entry.lastused) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_account_repository.h b/common/repositories/base/base_account_repository.h index 205a70ec1..b33310800 100644 --- a/common/repositories/base/base_account_repository.h +++ b/common/repositories/base/base_account_repository.h @@ -297,7 +297,7 @@ public: insert_values.push_back("'" + EscapeString(account_entry.ban_reason) + "'"); insert_values.push_back("'" + EscapeString(account_entry.suspend_reason) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_account_rewards_repository.h b/common/repositories/base/base_account_rewards_repository.h index 5ec33e1b7..e08eba9ad 100644 --- a/common/repositories/base/base_account_rewards_repository.h +++ b/common/repositories/base/base_account_rewards_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(account_rewards_entry.reward_id)); insert_values.push_back(std::to_string(account_rewards_entry.amount)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_adventure_details_repository.h b/common/repositories/base/base_adventure_details_repository.h index 5ee6e3d7e..afdaf82ab 100644 --- a/common/repositories/base/base_adventure_details_repository.h +++ b/common/repositories/base/base_adventure_details_repository.h @@ -237,7 +237,7 @@ public: insert_values.push_back(std::to_string(adventure_details_entry.time_zoned)); insert_values.push_back(std::to_string(adventure_details_entry.time_completed)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_adventure_members_repository.h b/common/repositories/base/base_adventure_members_repository.h index 4b6fcf2fc..1a2f5c15d 100644 --- a/common/repositories/base/base_adventure_members_repository.h +++ b/common/repositories/base/base_adventure_members_repository.h @@ -197,7 +197,7 @@ public: insert_values.push_back(std::to_string(adventure_members_entry.id)); insert_values.push_back(std::to_string(adventure_members_entry.charid)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_adventure_stats_repository.h b/common/repositories/base/base_adventure_stats_repository.h index 56008e648..62c3deaf5 100644 --- a/common/repositories/base/base_adventure_stats_repository.h +++ b/common/repositories/base/base_adventure_stats_repository.h @@ -251,7 +251,7 @@ public: insert_values.push_back(std::to_string(adventure_stats_entry.ruj_losses)); insert_values.push_back(std::to_string(adventure_stats_entry.tak_losses)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_adventure_template_entry_flavor_repository.h b/common/repositories/base/base_adventure_template_entry_flavor_repository.h index ff3a3c636..7950ae1cf 100644 --- a/common/repositories/base/base_adventure_template_entry_flavor_repository.h +++ b/common/repositories/base/base_adventure_template_entry_flavor_repository.h @@ -197,7 +197,7 @@ public: insert_values.push_back(std::to_string(adventure_template_entry_flavor_entry.id)); insert_values.push_back("'" + EscapeString(adventure_template_entry_flavor_entry.text) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_adventure_template_entry_repository.h b/common/repositories/base/base_adventure_template_entry_repository.h index cf86781ac..dae7e3f9e 100644 --- a/common/repositories/base/base_adventure_template_entry_repository.h +++ b/common/repositories/base/base_adventure_template_entry_repository.h @@ -197,7 +197,7 @@ public: insert_values.push_back(std::to_string(adventure_template_entry_entry.id)); insert_values.push_back(std::to_string(adventure_template_entry_entry.template_id)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_adventure_template_repository.h b/common/repositories/base/base_adventure_template_repository.h index 6857bda5a..aa1de97b5 100644 --- a/common/repositories/base/base_adventure_template_repository.h +++ b/common/repositories/base/base_adventure_template_repository.h @@ -383,7 +383,7 @@ public: insert_values.push_back(std::to_string(adventure_template_entry.graveyard_z)); insert_values.push_back(std::to_string(adventure_template_entry.graveyard_radius)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_alternate_currency_repository.h b/common/repositories/base/base_alternate_currency_repository.h index 722c90750..8b918690e 100644 --- a/common/repositories/base/base_alternate_currency_repository.h +++ b/common/repositories/base/base_alternate_currency_repository.h @@ -197,7 +197,7 @@ public: insert_values.push_back(std::to_string(alternate_currency_entry.id)); insert_values.push_back(std::to_string(alternate_currency_entry.item_id)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_auras_repository.h b/common/repositories/base/base_auras_repository.h index 859391361..b500b3e81 100644 --- a/common/repositories/base/base_auras_repository.h +++ b/common/repositories/base/base_auras_repository.h @@ -251,7 +251,7 @@ public: insert_values.push_back(std::to_string(auras_entry.icon)); insert_values.push_back(std::to_string(auras_entry.cast_time)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_base_data_repository.h b/common/repositories/base/base_base_data_repository.h index 6178cb9d4..e4a6aa8dc 100644 --- a/common/repositories/base/base_base_data_repository.h +++ b/common/repositories/base/base_base_data_repository.h @@ -245,7 +245,7 @@ public: insert_values.push_back(std::to_string(base_data_entry.mana_fac)); insert_values.push_back(std::to_string(base_data_entry.end_fac)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_blocked_spells_repository.h b/common/repositories/base/base_blocked_spells_repository.h index c47cf6cd2..a6f58bbb0 100644 --- a/common/repositories/base/base_blocked_spells_repository.h +++ b/common/repositories/base/base_blocked_spells_repository.h @@ -255,7 +255,7 @@ public: insert_values.push_back("'" + EscapeString(blocked_spells_entry.message) + "'"); insert_values.push_back("'" + EscapeString(blocked_spells_entry.description) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_bug_reports_repository.h b/common/repositories/base/base_bug_reports_repository.h index 5feea96d8..9e3cea3d2 100644 --- a/common/repositories/base/base_bug_reports_repository.h +++ b/common/repositories/base/base_bug_reports_repository.h @@ -375,7 +375,7 @@ public: insert_values.push_back("'" + EscapeString(bug_reports_entry.last_reviewer) + "'"); insert_values.push_back("'" + EscapeString(bug_reports_entry.reviewer_notes) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_bugs_repository.h b/common/repositories/base/base_bugs_repository.h index 79e193a7a..a6072991a 100644 --- a/common/repositories/base/base_bugs_repository.h +++ b/common/repositories/base/base_bugs_repository.h @@ -261,7 +261,7 @@ public: insert_values.push_back("'" + EscapeString(bugs_entry.date) + "'"); insert_values.push_back(std::to_string(bugs_entry.status)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_buyer_repository.h b/common/repositories/base/base_buyer_repository.h index 39148dac3..a0898fefd 100644 --- a/common/repositories/base/base_buyer_repository.h +++ b/common/repositories/base/base_buyer_repository.h @@ -221,7 +221,7 @@ public: insert_values.push_back(std::to_string(buyer_entry.quantity)); insert_values.push_back(std::to_string(buyer_entry.price)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_char_create_combinations_repository.h b/common/repositories/base/base_char_create_combinations_repository.h index 8f2d8ddb2..68c806a54 100644 --- a/common/repositories/base/base_char_create_combinations_repository.h +++ b/common/repositories/base/base_char_create_combinations_repository.h @@ -221,7 +221,7 @@ public: insert_values.push_back(std::to_string(char_create_combinations_entry.start_zone)); insert_values.push_back(std::to_string(char_create_combinations_entry.expansions_req)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_char_create_point_allocations_repository.h b/common/repositories/base/base_char_create_point_allocations_repository.h index 600e41e5d..04148a2d9 100644 --- a/common/repositories/base/base_char_create_point_allocations_repository.h +++ b/common/repositories/base/base_char_create_point_allocations_repository.h @@ -275,7 +275,7 @@ public: insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_wis)); insert_values.push_back(std::to_string(char_create_point_allocations_entry.alloc_cha)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_char_recipe_list_repository.h b/common/repositories/base/base_char_recipe_list_repository.h index 979d7f18b..0041a3032 100644 --- a/common/repositories/base/base_char_recipe_list_repository.h +++ b/common/repositories/base/base_char_recipe_list_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(char_recipe_list_entry.recipe_id)); insert_values.push_back(std::to_string(char_recipe_list_entry.madecount)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_activities_repository.h b/common/repositories/base/base_character_activities_repository.h index 7f3d05dae..3669d303b 100644 --- a/common/repositories/base/base_character_activities_repository.h +++ b/common/repositories/base/base_character_activities_repository.h @@ -215,7 +215,7 @@ public: insert_values.push_back(std::to_string(character_activities_entry.donecount)); insert_values.push_back(std::to_string(character_activities_entry.completed)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_alt_currency_repository.h b/common/repositories/base/base_character_alt_currency_repository.h index 300db63f4..7b97ebade 100644 --- a/common/repositories/base/base_character_alt_currency_repository.h +++ b/common/repositories/base/base_character_alt_currency_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(character_alt_currency_entry.currency_id)); insert_values.push_back(std::to_string(character_alt_currency_entry.amount)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_alternate_abilities_repository.h b/common/repositories/base/base_character_alternate_abilities_repository.h index 98171a33c..3adc61c53 100644 --- a/common/repositories/base/base_character_alternate_abilities_repository.h +++ b/common/repositories/base/base_character_alternate_abilities_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(character_alternate_abilities_entry.aa_value)); insert_values.push_back(std::to_string(character_alternate_abilities_entry.charges)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_auras_repository.h b/common/repositories/base/base_character_auras_repository.h index cc9fdedce..cef91dc07 100644 --- a/common/repositories/base/base_character_auras_repository.h +++ b/common/repositories/base/base_character_auras_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(character_auras_entry.slot)); insert_values.push_back(std::to_string(character_auras_entry.spell_id)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_bandolier_repository.h b/common/repositories/base/base_character_bandolier_repository.h index 3d58d17c7..be2c861d3 100644 --- a/common/repositories/base/base_character_bandolier_repository.h +++ b/common/repositories/base/base_character_bandolier_repository.h @@ -221,7 +221,7 @@ public: insert_values.push_back(std::to_string(character_bandolier_entry.icon)); insert_values.push_back("'" + EscapeString(character_bandolier_entry.bandolier_name) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_bind_repository.h b/common/repositories/base/base_character_bind_repository.h index e5920c4e1..ba9498781 100644 --- a/common/repositories/base/base_character_bind_repository.h +++ b/common/repositories/base/base_character_bind_repository.h @@ -231,7 +231,7 @@ public: insert_values.push_back(std::to_string(character_bind_entry.z)); insert_values.push_back(std::to_string(character_bind_entry.heading)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_buffs_repository.h b/common/repositories/base/base_character_buffs_repository.h index 9c8b53f42..77289fded 100644 --- a/common/repositories/base/base_character_buffs_repository.h +++ b/common/repositories/base/base_character_buffs_repository.h @@ -287,7 +287,7 @@ public: insert_values.push_back(std::to_string(character_buffs_entry.ExtraDIChance)); insert_values.push_back(std::to_string(character_buffs_entry.instrument_mod)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_corpse_items_repository.h b/common/repositories/base/base_character_corpse_items_repository.h index aa999c62f..9328d1aa0 100644 --- a/common/repositories/base/base_character_corpse_items_repository.h +++ b/common/repositories/base/base_character_corpse_items_repository.h @@ -251,7 +251,7 @@ public: insert_values.push_back(std::to_string(character_corpse_items_entry.aug_6)); insert_values.push_back(std::to_string(character_corpse_items_entry.attuned)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_corpses_repository.h b/common/repositories/base/base_character_corpses_repository.h index 4e0ee17f2..10379d109 100644 --- a/common/repositories/base/base_character_corpses_repository.h +++ b/common/repositories/base/base_character_corpses_repository.h @@ -465,7 +465,7 @@ public: insert_values.push_back(std::to_string(character_corpses_entry.wc_8)); insert_values.push_back(std::to_string(character_corpses_entry.wc_9)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_currency_repository.h b/common/repositories/base/base_character_currency_repository.h index 8eeb70244..462fba848 100644 --- a/common/repositories/base/base_character_currency_repository.h +++ b/common/repositories/base/base_character_currency_repository.h @@ -287,7 +287,7 @@ public: insert_values.push_back(std::to_string(character_currency_entry.ebon_crystals)); insert_values.push_back(std::to_string(character_currency_entry.career_ebon_crystals)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_data_repository.h b/common/repositories/base/base_character_data_repository.h index c76399ab4..ff06fa11b 100644 --- a/common/repositories/base/base_character_data_repository.h +++ b/common/repositories/base/base_character_data_repository.h @@ -795,7 +795,7 @@ public: insert_values.push_back(std::to_string(character_data_entry.e_last_invsnapshot)); insert_values.push_back("'" + EscapeString(character_data_entry.deleted_at) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_disciplines_repository.h b/common/repositories/base/base_character_disciplines_repository.h index a61dfbf6d..0a10e7288 100644 --- a/common/repositories/base/base_character_disciplines_repository.h +++ b/common/repositories/base/base_character_disciplines_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(character_disciplines_entry.slot_id)); insert_values.push_back(std::to_string(character_disciplines_entry.disc_id)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_expedition_lockouts_repository.h b/common/repositories/base/base_character_expedition_lockouts_repository.h index 492727298..705dacf10 100644 --- a/common/repositories/base/base_character_expedition_lockouts_repository.h +++ b/common/repositories/base/base_character_expedition_lockouts_repository.h @@ -225,7 +225,7 @@ public: insert_values.push_back(std::to_string(character_expedition_lockouts_entry.duration)); insert_values.push_back("'" + EscapeString(character_expedition_lockouts_entry.from_expedition_uuid) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_inspect_messages_repository.h b/common/repositories/base/base_character_inspect_messages_repository.h index e3088ded3..d5978defc 100644 --- a/common/repositories/base/base_character_inspect_messages_repository.h +++ b/common/repositories/base/base_character_inspect_messages_repository.h @@ -197,7 +197,7 @@ public: insert_values.push_back(std::to_string(character_inspect_messages_entry.id)); insert_values.push_back("'" + EscapeString(character_inspect_messages_entry.inspect_message) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_item_recast_repository.h b/common/repositories/base/base_character_item_recast_repository.h index 224380ac4..d86f795df 100644 --- a/common/repositories/base/base_character_item_recast_repository.h +++ b/common/repositories/base/base_character_item_recast_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(character_item_recast_entry.recast_type)); insert_values.push_back(std::to_string(character_item_recast_entry.timestamp)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_languages_repository.h b/common/repositories/base/base_character_languages_repository.h index 9a1519124..4c0bc6ac9 100644 --- a/common/repositories/base/base_character_languages_repository.h +++ b/common/repositories/base/base_character_languages_repository.h @@ -201,7 +201,7 @@ public: insert_values.push_back(std::to_string(character_languages_entry.lang_id)); insert_values.push_back(std::to_string(character_languages_entry.value)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_leadership_abilities_repository.h b/common/repositories/base/base_character_leadership_abilities_repository.h index ad340b07e..5482523a2 100644 --- a/common/repositories/base/base_character_leadership_abilities_repository.h +++ b/common/repositories/base/base_character_leadership_abilities_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(character_leadership_abilities_entry.slot)); insert_values.push_back(std::to_string(character_leadership_abilities_entry.rank)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_material_repository.h b/common/repositories/base/base_character_material_repository.h index 1fa174fe3..958c2d237 100644 --- a/common/repositories/base/base_character_material_repository.h +++ b/common/repositories/base/base_character_material_repository.h @@ -225,7 +225,7 @@ public: insert_values.push_back(std::to_string(character_material_entry.use_tint)); insert_values.push_back(std::to_string(character_material_entry.color)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_memmed_spells_repository.h b/common/repositories/base/base_character_memmed_spells_repository.h index ae080ccb5..33b789392 100644 --- a/common/repositories/base/base_character_memmed_spells_repository.h +++ b/common/repositories/base/base_character_memmed_spells_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(character_memmed_spells_entry.slot_id)); insert_values.push_back(std::to_string(character_memmed_spells_entry.spell_id)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_pet_buffs_repository.h b/common/repositories/base/base_character_pet_buffs_repository.h index 55206de76..4801262b2 100644 --- a/common/repositories/base/base_character_pet_buffs_repository.h +++ b/common/repositories/base/base_character_pet_buffs_repository.h @@ -251,7 +251,7 @@ public: insert_values.push_back(std::to_string(character_pet_buffs_entry.rune)); insert_values.push_back(std::to_string(character_pet_buffs_entry.instrument_mod)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_pet_info_repository.h b/common/repositories/base/base_character_pet_info_repository.h index 7d6685ce3..3d1c1c977 100644 --- a/common/repositories/base/base_character_pet_info_repository.h +++ b/common/repositories/base/base_character_pet_info_repository.h @@ -239,7 +239,7 @@ public: insert_values.push_back(std::to_string(character_pet_info_entry.size)); insert_values.push_back(std::to_string(character_pet_info_entry.taunting)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_pet_inventory_repository.h b/common/repositories/base/base_character_pet_inventory_repository.h index cff42805b..cb561d959 100644 --- a/common/repositories/base/base_character_pet_inventory_repository.h +++ b/common/repositories/base/base_character_pet_inventory_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(character_pet_inventory_entry.slot)); insert_values.push_back(std::to_string(character_pet_inventory_entry.item_id)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_potionbelt_repository.h b/common/repositories/base/base_character_potionbelt_repository.h index 32d30b0b4..1fce31537 100644 --- a/common/repositories/base/base_character_potionbelt_repository.h +++ b/common/repositories/base/base_character_potionbelt_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(character_potionbelt_entry.item_id)); insert_values.push_back(std::to_string(character_potionbelt_entry.icon)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_skills_repository.h b/common/repositories/base/base_character_skills_repository.h index f18a8b8a5..0b74eb410 100644 --- a/common/repositories/base/base_character_skills_repository.h +++ b/common/repositories/base/base_character_skills_repository.h @@ -201,7 +201,7 @@ public: insert_values.push_back(std::to_string(character_skills_entry.skill_id)); insert_values.push_back(std::to_string(character_skills_entry.value)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_spells_repository.h b/common/repositories/base/base_character_spells_repository.h index 76c811b34..13e007855 100644 --- a/common/repositories/base/base_character_spells_repository.h +++ b/common/repositories/base/base_character_spells_repository.h @@ -201,7 +201,7 @@ public: insert_values.push_back(std::to_string(character_spells_entry.slot_id)); insert_values.push_back(std::to_string(character_spells_entry.spell_id)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_character_tasks_repository.h b/common/repositories/base/base_character_tasks_repository.h index ddf9360ab..f7fa167db 100644 --- a/common/repositories/base/base_character_tasks_repository.h +++ b/common/repositories/base/base_character_tasks_repository.h @@ -215,7 +215,7 @@ public: insert_values.push_back(std::to_string(character_tasks_entry.type)); insert_values.push_back(std::to_string(character_tasks_entry.acceptedtime)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_completed_tasks_repository.h b/common/repositories/base/base_completed_tasks_repository.h index 2324dc5ea..023847085 100644 --- a/common/repositories/base/base_completed_tasks_repository.h +++ b/common/repositories/base/base_completed_tasks_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(completed_tasks_entry.taskid)); insert_values.push_back(std::to_string(completed_tasks_entry.activityid)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_content_flags_repository.h b/common/repositories/base/base_content_flags_repository.h index 76e25e7f2..d9b1e74d4 100644 --- a/common/repositories/base/base_content_flags_repository.h +++ b/common/repositories/base/base_content_flags_repository.h @@ -207,7 +207,7 @@ public: insert_values.push_back(std::to_string(content_flags_entry.enabled)); insert_values.push_back("'" + EscapeString(content_flags_entry.notes) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_damageshieldtypes_repository.h b/common/repositories/base/base_damageshieldtypes_repository.h index ae932940b..c16e4d18c 100644 --- a/common/repositories/base/base_damageshieldtypes_repository.h +++ b/common/repositories/base/base_damageshieldtypes_repository.h @@ -197,7 +197,7 @@ public: insert_values.push_back(std::to_string(damageshieldtypes_entry.spellid)); insert_values.push_back(std::to_string(damageshieldtypes_entry.type)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_data_buckets_repository.h b/common/repositories/base/base_data_buckets_repository.h index 622af41b9..91138da9a 100644 --- a/common/repositories/base/base_data_buckets_repository.h +++ b/common/repositories/base/base_data_buckets_repository.h @@ -207,7 +207,7 @@ public: insert_values.push_back("'" + EscapeString(data_buckets_entry.value) + "'"); insert_values.push_back(std::to_string(data_buckets_entry.expires)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_db_str_repository.h b/common/repositories/base/base_db_str_repository.h index bda720ec8..036950948 100644 --- a/common/repositories/base/base_db_str_repository.h +++ b/common/repositories/base/base_db_str_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(db_str_entry.type)); insert_values.push_back("'" + EscapeString(db_str_entry.value) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_discovered_items_repository.h b/common/repositories/base/base_discovered_items_repository.h index f91d4e11c..08ecba827 100644 --- a/common/repositories/base/base_discovered_items_repository.h +++ b/common/repositories/base/base_discovered_items_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(discovered_items_entry.discovered_date)); insert_values.push_back(std::to_string(discovered_items_entry.account_status)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_doors_repository.h b/common/repositories/base/base_doors_repository.h index cb746503d..ca554749f 100644 --- a/common/repositories/base/base_doors_repository.h +++ b/common/repositories/base/base_doors_repository.h @@ -393,7 +393,7 @@ public: insert_values.push_back("'" + EscapeString(doors_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(doors_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_dynamic_zones_repository.h b/common/repositories/base/base_dynamic_zones_repository.h index faab30727..6a930330b 100644 --- a/common/repositories/base/base_dynamic_zones_repository.h +++ b/common/repositories/base/base_dynamic_zones_repository.h @@ -285,7 +285,7 @@ public: insert_values.push_back(std::to_string(dynamic_zones_entry.zone_in_heading)); insert_values.push_back(std::to_string(dynamic_zones_entry.has_zone_in)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_eventlog_repository.h b/common/repositories/base/base_eventlog_repository.h index c72ad0d1c..5c134adaf 100644 --- a/common/repositories/base/base_eventlog_repository.h +++ b/common/repositories/base/base_eventlog_repository.h @@ -243,7 +243,7 @@ public: insert_values.push_back("'" + EscapeString(eventlog_entry.description) + "'"); insert_values.push_back(std::to_string(eventlog_entry.event_nid)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_expedition_lockouts_repository.h b/common/repositories/base/base_expedition_lockouts_repository.h index 20f92f80c..96ef8677a 100644 --- a/common/repositories/base/base_expedition_lockouts_repository.h +++ b/common/repositories/base/base_expedition_lockouts_repository.h @@ -219,7 +219,7 @@ public: insert_values.push_back(std::to_string(expedition_lockouts_entry.duration)); insert_values.push_back("'" + EscapeString(expedition_lockouts_entry.from_expedition_uuid) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_expedition_members_repository.h b/common/repositories/base/base_expedition_members_repository.h index 36778acb0..a5628a3d7 100644 --- a/common/repositories/base/base_expedition_members_repository.h +++ b/common/repositories/base/base_expedition_members_repository.h @@ -207,7 +207,7 @@ public: insert_values.push_back(std::to_string(expedition_members_entry.character_id)); insert_values.push_back(std::to_string(expedition_members_entry.is_current_member)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_expeditions_repository.h b/common/repositories/base/base_expeditions_repository.h index 330428b41..5eaadb9a6 100644 --- a/common/repositories/base/base_expeditions_repository.h +++ b/common/repositories/base/base_expeditions_repository.h @@ -237,7 +237,7 @@ public: insert_values.push_back(std::to_string(expeditions_entry.add_replay_on_join)); insert_values.push_back(std::to_string(expeditions_entry.is_locked)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_faction_base_data_repository.h b/common/repositories/base/base_faction_base_data_repository.h index 09aa8f413..faa099dfd 100644 --- a/common/repositories/base/base_faction_base_data_repository.h +++ b/common/repositories/base/base_faction_base_data_repository.h @@ -221,7 +221,7 @@ public: insert_values.push_back(std::to_string(faction_base_data_entry.unk_hero2)); insert_values.push_back(std::to_string(faction_base_data_entry.unk_hero3)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_faction_list_mod_repository.h b/common/repositories/base/base_faction_list_mod_repository.h index 9c91ebee9..136de8703 100644 --- a/common/repositories/base/base_faction_list_mod_repository.h +++ b/common/repositories/base/base_faction_list_mod_repository.h @@ -207,7 +207,7 @@ public: insert_values.push_back(std::to_string(faction_list_mod_entry.mod)); insert_values.push_back("'" + EscapeString(faction_list_mod_entry.mod_name) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_faction_list_repository.h b/common/repositories/base/base_faction_list_repository.h index 08b4ae16a..870f6335f 100644 --- a/common/repositories/base/base_faction_list_repository.h +++ b/common/repositories/base/base_faction_list_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back("'" + EscapeString(faction_list_entry.name) + "'"); insert_values.push_back(std::to_string(faction_list_entry.base)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_faction_values_repository.h b/common/repositories/base/base_faction_values_repository.h index 999c01806..63fbd2597 100644 --- a/common/repositories/base/base_faction_values_repository.h +++ b/common/repositories/base/base_faction_values_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(faction_values_entry.current_value)); insert_values.push_back(std::to_string(faction_values_entry.temp)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_fishing_repository.h b/common/repositories/base/base_fishing_repository.h index 73515df6e..8ba5d7517 100644 --- a/common/repositories/base/base_fishing_repository.h +++ b/common/repositories/base/base_fishing_repository.h @@ -249,7 +249,7 @@ public: insert_values.push_back("'" + EscapeString(fishing_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(fishing_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_forage_repository.h b/common/repositories/base/base_forage_repository.h index f279f1532..6fda9ba2d 100644 --- a/common/repositories/base/base_forage_repository.h +++ b/common/repositories/base/base_forage_repository.h @@ -237,7 +237,7 @@ public: insert_values.push_back("'" + EscapeString(forage_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(forage_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_friends_repository.h b/common/repositories/base/base_friends_repository.h index 5b75b6f64..64a2042d6 100644 --- a/common/repositories/base/base_friends_repository.h +++ b/common/repositories/base/base_friends_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(friends_entry.type)); insert_values.push_back("'" + EscapeString(friends_entry.name) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_global_loot_repository.h b/common/repositories/base/base_global_loot_repository.h index e2d0d5822..87ebc18f3 100644 --- a/common/repositories/base/base_global_loot_repository.h +++ b/common/repositories/base/base_global_loot_repository.h @@ -285,7 +285,7 @@ public: insert_values.push_back("'" + EscapeString(global_loot_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(global_loot_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_gm_ips_repository.h b/common/repositories/base/base_gm_ips_repository.h index 6ce5814ea..84c124b83 100644 --- a/common/repositories/base/base_gm_ips_repository.h +++ b/common/repositories/base/base_gm_ips_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(gm_ips_entry.account_id)); insert_values.push_back("'" + EscapeString(gm_ips_entry.ip_address) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_goallists_repository.h b/common/repositories/base/base_goallists_repository.h index 15ab5c174..68de11598 100644 --- a/common/repositories/base/base_goallists_repository.h +++ b/common/repositories/base/base_goallists_repository.h @@ -197,7 +197,7 @@ public: insert_values.push_back(std::to_string(goallists_entry.listid)); insert_values.push_back(std::to_string(goallists_entry.entry)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_graveyard_repository.h b/common/repositories/base/base_graveyard_repository.h index 942ea3736..54cc24657 100644 --- a/common/repositories/base/base_graveyard_repository.h +++ b/common/repositories/base/base_graveyard_repository.h @@ -219,7 +219,7 @@ public: insert_values.push_back(std::to_string(graveyard_entry.z)); insert_values.push_back(std::to_string(graveyard_entry.heading)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_ground_spawns_repository.h b/common/repositories/base/base_ground_spawns_repository.h index 308282e2c..f4be68297 100644 --- a/common/repositories/base/base_ground_spawns_repository.h +++ b/common/repositories/base/base_ground_spawns_repository.h @@ -291,7 +291,7 @@ public: insert_values.push_back("'" + EscapeString(ground_spawns_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(ground_spawns_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_group_id_repository.h b/common/repositories/base/base_group_id_repository.h index f0147e40f..d607541d1 100644 --- a/common/repositories/base/base_group_id_repository.h +++ b/common/repositories/base/base_group_id_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back("'" + EscapeString(group_id_entry.name) + "'"); insert_values.push_back(std::to_string(group_id_entry.ismerc)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_group_leaders_repository.h b/common/repositories/base/base_group_leaders_repository.h index f518e0d09..fc5264ef8 100644 --- a/common/repositories/base/base_group_leaders_repository.h +++ b/common/repositories/base/base_group_leaders_repository.h @@ -239,7 +239,7 @@ public: insert_values.push_back("'" + EscapeString(group_leaders_entry.mentoree) + "'"); insert_values.push_back(std::to_string(group_leaders_entry.mentor_percent)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_guild_members_repository.h b/common/repositories/base/base_guild_members_repository.h index 9ff83b91b..518150b61 100644 --- a/common/repositories/base/base_guild_members_repository.h +++ b/common/repositories/base/base_guild_members_repository.h @@ -239,7 +239,7 @@ public: insert_values.push_back("'" + EscapeString(guild_members_entry.public_note) + "'"); insert_values.push_back(std::to_string(guild_members_entry.alt)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_guild_ranks_repository.h b/common/repositories/base/base_guild_ranks_repository.h index 1d6375c70..d136defb3 100644 --- a/common/repositories/base/base_guild_ranks_repository.h +++ b/common/repositories/base/base_guild_ranks_repository.h @@ -251,7 +251,7 @@ public: insert_values.push_back(std::to_string(guild_ranks_entry.can_motd)); insert_values.push_back(std::to_string(guild_ranks_entry.can_warpeace)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_guild_relations_repository.h b/common/repositories/base/base_guild_relations_repository.h index 87359e110..7ea85b4a0 100644 --- a/common/repositories/base/base_guild_relations_repository.h +++ b/common/repositories/base/base_guild_relations_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(guild_relations_entry.guild2)); insert_values.push_back(std::to_string(guild_relations_entry.relation)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_guilds_repository.h b/common/repositories/base/base_guilds_repository.h index eb7d17046..312247a20 100644 --- a/common/repositories/base/base_guilds_repository.h +++ b/common/repositories/base/base_guilds_repository.h @@ -237,7 +237,7 @@ public: insert_values.push_back("'" + EscapeString(guilds_entry.channel) + "'"); insert_values.push_back("'" + EscapeString(guilds_entry.url) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_hackers_repository.h b/common/repositories/base/base_hackers_repository.h index e219e3a04..5dcf5fba3 100644 --- a/common/repositories/base/base_hackers_repository.h +++ b/common/repositories/base/base_hackers_repository.h @@ -219,7 +219,7 @@ public: insert_values.push_back("'" + EscapeString(hackers_entry.zone) + "'"); insert_values.push_back("'" + EscapeString(hackers_entry.date) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_instance_list_player_repository.h b/common/repositories/base/base_instance_list_player_repository.h index 43a6e0725..66553cca0 100644 --- a/common/repositories/base/base_instance_list_player_repository.h +++ b/common/repositories/base/base_instance_list_player_repository.h @@ -197,7 +197,7 @@ public: insert_values.push_back(std::to_string(instance_list_player_entry.id)); insert_values.push_back(std::to_string(instance_list_player_entry.charid)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_instance_list_repository.h b/common/repositories/base/base_instance_list_repository.h index 02eba1606..dbe5a0dd2 100644 --- a/common/repositories/base/base_instance_list_repository.h +++ b/common/repositories/base/base_instance_list_repository.h @@ -225,7 +225,7 @@ public: insert_values.push_back(std::to_string(instance_list_entry.duration)); insert_values.push_back(std::to_string(instance_list_entry.never_expires)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_inventory_repository.h b/common/repositories/base/base_inventory_repository.h index 09d497101..3deb76fd7 100644 --- a/common/repositories/base/base_inventory_repository.h +++ b/common/repositories/base/base_inventory_repository.h @@ -281,7 +281,7 @@ public: insert_values.push_back(std::to_string(inventory_entry.ornamentidfile)); insert_values.push_back(std::to_string(inventory_entry.ornament_hero_model)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_inventory_snapshots_repository.h b/common/repositories/base/base_inventory_snapshots_repository.h index e5645f25a..a31e91da7 100644 --- a/common/repositories/base/base_inventory_snapshots_repository.h +++ b/common/repositories/base/base_inventory_snapshots_repository.h @@ -287,7 +287,7 @@ public: insert_values.push_back(std::to_string(inventory_snapshots_entry.ornamentidfile)); insert_values.push_back(std::to_string(inventory_snapshots_entry.ornament_hero_model)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_ip_exemptions_repository.h b/common/repositories/base/base_ip_exemptions_repository.h index d163f1c1f..e673d18d2 100644 --- a/common/repositories/base/base_ip_exemptions_repository.h +++ b/common/repositories/base/base_ip_exemptions_repository.h @@ -201,7 +201,7 @@ public: insert_values.push_back("'" + EscapeString(ip_exemptions_entry.exemption_ip) + "'"); insert_values.push_back(std::to_string(ip_exemptions_entry.exemption_amount)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_item_tick_repository.h b/common/repositories/base/base_item_tick_repository.h index edba624b7..5d788acca 100644 --- a/common/repositories/base/base_item_tick_repository.h +++ b/common/repositories/base/base_item_tick_repository.h @@ -219,7 +219,7 @@ public: insert_values.push_back("'" + EscapeString(item_tick_entry.it_qglobal) + "'"); insert_values.push_back(std::to_string(item_tick_entry.it_bagslot)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_items_repository.h b/common/repositories/base/base_items_repository.h index af99a05da..c309bc1b6 100644 --- a/common/repositories/base/base_items_repository.h +++ b/common/repositories/base/base_items_repository.h @@ -1895,7 +1895,7 @@ public: insert_values.push_back(std::to_string(items_entry.UNK241)); insert_values.push_back(std::to_string(items_entry.epicitem)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_ldon_trap_entries_repository.h b/common/repositories/base/base_ldon_trap_entries_repository.h index 5004afb65..86ab6e8f2 100644 --- a/common/repositories/base/base_ldon_trap_entries_repository.h +++ b/common/repositories/base/base_ldon_trap_entries_repository.h @@ -197,7 +197,7 @@ public: insert_values.push_back(std::to_string(ldon_trap_entries_entry.id)); insert_values.push_back(std::to_string(ldon_trap_entries_entry.trap_id)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_ldon_trap_templates_repository.h b/common/repositories/base/base_ldon_trap_templates_repository.h index 256a5102c..396345ea8 100644 --- a/common/repositories/base/base_ldon_trap_templates_repository.h +++ b/common/repositories/base/base_ldon_trap_templates_repository.h @@ -215,7 +215,7 @@ public: insert_values.push_back(std::to_string(ldon_trap_templates_entry.skill)); insert_values.push_back(std::to_string(ldon_trap_templates_entry.locked)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_level_exp_mods_repository.h b/common/repositories/base/base_level_exp_mods_repository.h index 9a7754b98..47fb482c3 100644 --- a/common/repositories/base/base_level_exp_mods_repository.h +++ b/common/repositories/base/base_level_exp_mods_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(level_exp_mods_entry.exp_mod)); insert_values.push_back(std::to_string(level_exp_mods_entry.aa_exp_mod)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_lfguild_repository.h b/common/repositories/base/base_lfguild_repository.h index 6fe079d2e..39a32a5c8 100644 --- a/common/repositories/base/base_lfguild_repository.h +++ b/common/repositories/base/base_lfguild_repository.h @@ -239,7 +239,7 @@ public: insert_values.push_back(std::to_string(lfguild_entry.timezone)); insert_values.push_back(std::to_string(lfguild_entry.timeposted)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_login_accounts_repository.h b/common/repositories/base/base_login_accounts_repository.h index 43084859b..767ea0ead 100644 --- a/common/repositories/base/base_login_accounts_repository.h +++ b/common/repositories/base/base_login_accounts_repository.h @@ -239,7 +239,7 @@ public: insert_values.push_back("'" + EscapeString(login_accounts_entry.created_at) + "'"); insert_values.push_back("'" + EscapeString(login_accounts_entry.updated_at) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_login_api_tokens_repository.h b/common/repositories/base/base_login_api_tokens_repository.h index 92bb75642..20be8143a 100644 --- a/common/repositories/base/base_login_api_tokens_repository.h +++ b/common/repositories/base/base_login_api_tokens_repository.h @@ -219,7 +219,7 @@ public: insert_values.push_back("'" + EscapeString(login_api_tokens_entry.created_at) + "'"); insert_values.push_back("'" + EscapeString(login_api_tokens_entry.updated_at) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_login_server_admins_repository.h b/common/repositories/base/base_login_server_admins_repository.h index b819a1d11..6d25eb4c9 100644 --- a/common/repositories/base/base_login_server_admins_repository.h +++ b/common/repositories/base/base_login_server_admins_repository.h @@ -231,7 +231,7 @@ public: insert_values.push_back("'" + EscapeString(login_server_admins_entry.registration_date) + "'"); insert_values.push_back("'" + EscapeString(login_server_admins_entry.registration_ip_address) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_login_server_list_types_repository.h b/common/repositories/base/base_login_server_list_types_repository.h index a7d5eec1a..5508e3704 100644 --- a/common/repositories/base/base_login_server_list_types_repository.h +++ b/common/repositories/base/base_login_server_list_types_repository.h @@ -197,7 +197,7 @@ public: insert_values.push_back(std::to_string(login_server_list_types_entry.id)); insert_values.push_back("'" + EscapeString(login_server_list_types_entry.description) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_login_world_servers_repository.h b/common/repositories/base/base_login_world_servers_repository.h index 37435d4f5..8a21dc6b5 100644 --- a/common/repositories/base/base_login_world_servers_repository.h +++ b/common/repositories/base/base_login_world_servers_repository.h @@ -243,7 +243,7 @@ public: insert_values.push_back(std::to_string(login_world_servers_entry.is_server_trusted)); insert_values.push_back("'" + EscapeString(login_world_servers_entry.note) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_logsys_categories_repository.h b/common/repositories/base/base_logsys_categories_repository.h index e11965956..380897a76 100644 --- a/common/repositories/base/base_logsys_categories_repository.h +++ b/common/repositories/base/base_logsys_categories_repository.h @@ -215,7 +215,7 @@ public: insert_values.push_back(std::to_string(logsys_categories_entry.log_to_file)); insert_values.push_back(std::to_string(logsys_categories_entry.log_to_gmsay)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_lootdrop_entries_repository.h b/common/repositories/base/base_lootdrop_entries_repository.h index 872c7e87a..48d33f130 100644 --- a/common/repositories/base/base_lootdrop_entries_repository.h +++ b/common/repositories/base/base_lootdrop_entries_repository.h @@ -251,7 +251,7 @@ public: insert_values.push_back(std::to_string(lootdrop_entries_entry.npc_min_level)); insert_values.push_back(std::to_string(lootdrop_entries_entry.npc_max_level)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_lootdrop_repository.h b/common/repositories/base/base_lootdrop_repository.h index 9cd141f90..a0da43c83 100644 --- a/common/repositories/base/base_lootdrop_repository.h +++ b/common/repositories/base/base_lootdrop_repository.h @@ -219,7 +219,7 @@ public: insert_values.push_back("'" + EscapeString(lootdrop_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(lootdrop_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_loottable_entries_repository.h b/common/repositories/base/base_loottable_entries_repository.h index 113fe8094..52a8a738c 100644 --- a/common/repositories/base/base_loottable_entries_repository.h +++ b/common/repositories/base/base_loottable_entries_repository.h @@ -221,7 +221,7 @@ public: insert_values.push_back(std::to_string(loottable_entries_entry.mindrop)); insert_values.push_back(std::to_string(loottable_entries_entry.probability)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_loottable_repository.h b/common/repositories/base/base_loottable_repository.h index 81e12b02f..e0ab61a00 100644 --- a/common/repositories/base/base_loottable_repository.h +++ b/common/repositories/base/base_loottable_repository.h @@ -243,7 +243,7 @@ public: insert_values.push_back("'" + EscapeString(loottable_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(loottable_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_mail_repository.h b/common/repositories/base/base_mail_repository.h index f36028c80..39d2a086c 100644 --- a/common/repositories/base/base_mail_repository.h +++ b/common/repositories/base/base_mail_repository.h @@ -231,7 +231,7 @@ public: insert_values.push_back("'" + EscapeString(mail_entry.to) + "'"); insert_values.push_back(std::to_string(mail_entry.status)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_merchantlist_repository.h b/common/repositories/base/base_merchantlist_repository.h index 05e0adce3..2b87bc7b6 100644 --- a/common/repositories/base/base_merchantlist_repository.h +++ b/common/repositories/base/base_merchantlist_repository.h @@ -257,7 +257,7 @@ public: insert_values.push_back("'" + EscapeString(merchantlist_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(merchantlist_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_merchantlist_temp_repository.h b/common/repositories/base/base_merchantlist_temp_repository.h index a3c347e57..87d96dfb1 100644 --- a/common/repositories/base/base_merchantlist_temp_repository.h +++ b/common/repositories/base/base_merchantlist_temp_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(merchantlist_temp_entry.itemid)); insert_values.push_back(std::to_string(merchantlist_temp_entry.charges)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_name_filter_repository.h b/common/repositories/base/base_name_filter_repository.h index 1dfc8fb0b..93273046a 100644 --- a/common/repositories/base/base_name_filter_repository.h +++ b/common/repositories/base/base_name_filter_repository.h @@ -195,7 +195,7 @@ public: insert_values.push_back("'" + EscapeString(name_filter_entry.name) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_npc_emotes_repository.h b/common/repositories/base/base_npc_emotes_repository.h index c312fac61..c32939af1 100644 --- a/common/repositories/base/base_npc_emotes_repository.h +++ b/common/repositories/base/base_npc_emotes_repository.h @@ -213,7 +213,7 @@ public: insert_values.push_back(std::to_string(npc_emotes_entry.type)); insert_values.push_back("'" + EscapeString(npc_emotes_entry.text) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_npc_faction_entries_repository.h b/common/repositories/base/base_npc_faction_entries_repository.h index 25589d42e..5ce90f273 100644 --- a/common/repositories/base/base_npc_faction_entries_repository.h +++ b/common/repositories/base/base_npc_faction_entries_repository.h @@ -215,7 +215,7 @@ public: insert_values.push_back(std::to_string(npc_faction_entries_entry.npc_value)); insert_values.push_back(std::to_string(npc_faction_entries_entry.temp)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_npc_faction_repository.h b/common/repositories/base/base_npc_faction_repository.h index 2325fc4c2..22435c946 100644 --- a/common/repositories/base/base_npc_faction_repository.h +++ b/common/repositories/base/base_npc_faction_repository.h @@ -207,7 +207,7 @@ public: insert_values.push_back(std::to_string(npc_faction_entry.primaryfaction)); insert_values.push_back(std::to_string(npc_faction_entry.ignore_primary_assist)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_npc_scale_global_base_repository.h b/common/repositories/base/base_npc_scale_global_base_repository.h index 954bb2636..186018ad7 100644 --- a/common/repositories/base/base_npc_scale_global_base_repository.h +++ b/common/repositories/base/base_npc_scale_global_base_repository.h @@ -353,7 +353,7 @@ public: insert_values.push_back(std::to_string(npc_scale_global_base_entry.heal_scale)); insert_values.push_back("'" + EscapeString(npc_scale_global_base_entry.special_abilities) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_npc_spells_effects_entries_repository.h b/common/repositories/base/base_npc_spells_effects_entries_repository.h index 589e42d67..3d12df705 100644 --- a/common/repositories/base/base_npc_spells_effects_entries_repository.h +++ b/common/repositories/base/base_npc_spells_effects_entries_repository.h @@ -231,7 +231,7 @@ public: insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.se_limit)); insert_values.push_back(std::to_string(npc_spells_effects_entries_entry.se_max)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_npc_spells_effects_repository.h b/common/repositories/base/base_npc_spells_effects_repository.h index 5803258be..b8e75e8d1 100644 --- a/common/repositories/base/base_npc_spells_effects_repository.h +++ b/common/repositories/base/base_npc_spells_effects_repository.h @@ -201,7 +201,7 @@ public: insert_values.push_back("'" + EscapeString(npc_spells_effects_entry.name) + "'"); insert_values.push_back(std::to_string(npc_spells_effects_entry.parent_list)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_npc_spells_entries_repository.h b/common/repositories/base/base_npc_spells_entries_repository.h index 58192ed7a..06f53c42a 100644 --- a/common/repositories/base/base_npc_spells_entries_repository.h +++ b/common/repositories/base/base_npc_spells_entries_repository.h @@ -255,7 +255,7 @@ public: insert_values.push_back(std::to_string(npc_spells_entries_entry.min_hp)); insert_values.push_back(std::to_string(npc_spells_entries_entry.max_hp)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_npc_spells_repository.h b/common/repositories/base/base_npc_spells_repository.h index ccf1791b0..b99c67bf3 100644 --- a/common/repositories/base/base_npc_spells_repository.h +++ b/common/repositories/base/base_npc_spells_repository.h @@ -309,7 +309,7 @@ public: insert_values.push_back(std::to_string(npc_spells_entry.idle_no_sp_recast_max)); insert_values.push_back(std::to_string(npc_spells_entry.idle_b_chance)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_npc_types_repository.h b/common/repositories/base/base_npc_types_repository.h index ea8452aa6..8c8fcf116 100644 --- a/common/repositories/base/base_npc_types_repository.h +++ b/common/repositories/base/base_npc_types_repository.h @@ -915,7 +915,7 @@ public: insert_values.push_back(std::to_string(npc_types_entry.flymode)); insert_values.push_back(std::to_string(npc_types_entry.always_aggro)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_npc_types_tint_repository.h b/common/repositories/base/base_npc_types_tint_repository.h index 9de65e925..dc4a1bbdf 100644 --- a/common/repositories/base/base_npc_types_tint_repository.h +++ b/common/repositories/base/base_npc_types_tint_repository.h @@ -359,7 +359,7 @@ public: insert_values.push_back(std::to_string(npc_types_tint_entry.grn9x)); insert_values.push_back(std::to_string(npc_types_tint_entry.blu9x)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_object_contents_repository.h b/common/repositories/base/base_object_contents_repository.h index 5e59200f2..c73145c6d 100644 --- a/common/repositories/base/base_object_contents_repository.h +++ b/common/repositories/base/base_object_contents_repository.h @@ -257,7 +257,7 @@ public: insert_values.push_back(std::to_string(object_contents_entry.augslot5)); insert_values.push_back(std::to_string(object_contents_entry.augslot6)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_object_repository.h b/common/repositories/base/base_object_repository.h index cd3a02e01..f2659d7a1 100644 --- a/common/repositories/base/base_object_repository.h +++ b/common/repositories/base/base_object_repository.h @@ -363,7 +363,7 @@ public: insert_values.push_back("'" + EscapeString(object_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(object_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_perl_event_export_settings_repository.h b/common/repositories/base/base_perl_event_export_settings_repository.h index 35f236a29..b54bf825f 100644 --- a/common/repositories/base/base_perl_event_export_settings_repository.h +++ b/common/repositories/base/base_perl_event_export_settings_repository.h @@ -227,7 +227,7 @@ public: insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_item)); insert_values.push_back(std::to_string(perl_event_export_settings_entry.export_event)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_petitions_repository.h b/common/repositories/base/base_petitions_repository.h index d0aedad7e..c9cabfee8 100644 --- a/common/repositories/base/base_petitions_repository.h +++ b/common/repositories/base/base_petitions_repository.h @@ -279,7 +279,7 @@ public: insert_values.push_back(std::to_string(petitions_entry.ischeckedout)); insert_values.push_back(std::to_string(petitions_entry.senttime)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_pets_equipmentset_entries_repository.h b/common/repositories/base/base_pets_equipmentset_entries_repository.h index 6dc1f6261..2bf2f52e7 100644 --- a/common/repositories/base/base_pets_equipmentset_entries_repository.h +++ b/common/repositories/base/base_pets_equipmentset_entries_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back(std::to_string(pets_equipmentset_entries_entry.slot)); insert_values.push_back(std::to_string(pets_equipmentset_entries_entry.item_id)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_pets_equipmentset_repository.h b/common/repositories/base/base_pets_equipmentset_repository.h index 1015a8144..c041477c3 100644 --- a/common/repositories/base/base_pets_equipmentset_repository.h +++ b/common/repositories/base/base_pets_equipmentset_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back("'" + EscapeString(pets_equipmentset_entry.setname) + "'"); insert_values.push_back(std::to_string(pets_equipmentset_entry.nested_set)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_pets_repository.h b/common/repositories/base/base_pets_repository.h index 623c7cb67..ef4ddf7f1 100644 --- a/common/repositories/base/base_pets_repository.h +++ b/common/repositories/base/base_pets_repository.h @@ -233,7 +233,7 @@ public: insert_values.push_back(std::to_string(pets_entry.monsterflag)); insert_values.push_back(std::to_string(pets_entry.equipmentset)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_player_titlesets_repository.h b/common/repositories/base/base_player_titlesets_repository.h index f7562d5e6..4378090a6 100644 --- a/common/repositories/base/base_player_titlesets_repository.h +++ b/common/repositories/base/base_player_titlesets_repository.h @@ -201,7 +201,7 @@ public: insert_values.push_back(std::to_string(player_titlesets_entry.char_id)); insert_values.push_back(std::to_string(player_titlesets_entry.title_set)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_proximities_repository.h b/common/repositories/base/base_proximities_repository.h index 880a9fa97..2495da016 100644 --- a/common/repositories/base/base_proximities_repository.h +++ b/common/repositories/base/base_proximities_repository.h @@ -233,7 +233,7 @@ public: insert_values.push_back(std::to_string(proximities_entry.minz)); insert_values.push_back(std::to_string(proximities_entry.maxz)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_quest_globals_repository.h b/common/repositories/base/base_quest_globals_repository.h index 69b2a991f..0b20020e8 100644 --- a/common/repositories/base/base_quest_globals_repository.h +++ b/common/repositories/base/base_quest_globals_repository.h @@ -221,7 +221,7 @@ public: insert_values.push_back("'" + EscapeString(quest_globals_entry.value) + "'"); insert_values.push_back(std::to_string(quest_globals_entry.expdate)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_raid_details_repository.h b/common/repositories/base/base_raid_details_repository.h index 039d773a9..fc00b12be 100644 --- a/common/repositories/base/base_raid_details_repository.h +++ b/common/repositories/base/base_raid_details_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(raid_details_entry.locked)); insert_values.push_back("'" + EscapeString(raid_details_entry.motd) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_raid_members_repository.h b/common/repositories/base/base_raid_members_repository.h index 6483f26a7..983475640 100644 --- a/common/repositories/base/base_raid_members_repository.h +++ b/common/repositories/base/base_raid_members_repository.h @@ -239,7 +239,7 @@ public: insert_values.push_back(std::to_string(raid_members_entry.israidleader)); insert_values.push_back(std::to_string(raid_members_entry.islooter)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_reports_repository.h b/common/repositories/base/base_reports_repository.h index cc1ccfe5f..c3842c923 100644 --- a/common/repositories/base/base_reports_repository.h +++ b/common/repositories/base/base_reports_repository.h @@ -207,7 +207,7 @@ public: insert_values.push_back("'" + EscapeString(reports_entry.reported) + "'"); insert_values.push_back("'" + EscapeString(reports_entry.reported_text) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_respawn_times_repository.h b/common/repositories/base/base_respawn_times_repository.h index c234d3e5b..16fd1f2ef 100644 --- a/common/repositories/base/base_respawn_times_repository.h +++ b/common/repositories/base/base_respawn_times_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(respawn_times_entry.duration)); insert_values.push_back(std::to_string(respawn_times_entry.instance_id)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_rule_sets_repository.h b/common/repositories/base/base_rule_sets_repository.h index e3306ff04..2c6a4d679 100644 --- a/common/repositories/base/base_rule_sets_repository.h +++ b/common/repositories/base/base_rule_sets_repository.h @@ -195,7 +195,7 @@ public: insert_values.push_back("'" + EscapeString(rule_sets_entry.name) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_rule_values_repository.h b/common/repositories/base/base_rule_values_repository.h index 38d4eb1c5..44bce4518 100644 --- a/common/repositories/base/base_rule_values_repository.h +++ b/common/repositories/base/base_rule_values_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back("'" + EscapeString(rule_values_entry.rule_value) + "'"); insert_values.push_back("'" + EscapeString(rule_values_entry.notes) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_saylink_repository.h b/common/repositories/base/base_saylink_repository.h index aabb535e3..1bfc00807 100644 --- a/common/repositories/base/base_saylink_repository.h +++ b/common/repositories/base/base_saylink_repository.h @@ -195,7 +195,7 @@ public: insert_values.push_back("'" + EscapeString(saylink_entry.phrase) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_skill_caps_repository.h b/common/repositories/base/base_skill_caps_repository.h index 5ceee4757..fcafdcf48 100644 --- a/common/repositories/base/base_skill_caps_repository.h +++ b/common/repositories/base/base_skill_caps_repository.h @@ -215,7 +215,7 @@ public: insert_values.push_back(std::to_string(skill_caps_entry.cap)); insert_values.push_back(std::to_string(skill_caps_entry.class_)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_spawn2_repository.h b/common/repositories/base/base_spawn2_repository.h index 0006a9581..ce4d12ba8 100644 --- a/common/repositories/base/base_spawn2_repository.h +++ b/common/repositories/base/base_spawn2_repository.h @@ -297,7 +297,7 @@ public: insert_values.push_back("'" + EscapeString(spawn2_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(spawn2_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_spawn_condition_values_repository.h b/common/repositories/base/base_spawn_condition_values_repository.h index 209db098b..9a0d1668b 100644 --- a/common/repositories/base/base_spawn_condition_values_repository.h +++ b/common/repositories/base/base_spawn_condition_values_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back("'" + EscapeString(spawn_condition_values_entry.zone) + "'"); insert_values.push_back(std::to_string(spawn_condition_values_entry.instance_id)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_spawn_conditions_repository.h b/common/repositories/base/base_spawn_conditions_repository.h index 343e3887c..c4bc27594 100644 --- a/common/repositories/base/base_spawn_conditions_repository.h +++ b/common/repositories/base/base_spawn_conditions_repository.h @@ -215,7 +215,7 @@ public: insert_values.push_back(std::to_string(spawn_conditions_entry.onchange)); insert_values.push_back("'" + EscapeString(spawn_conditions_entry.name) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_spawn_events_repository.h b/common/repositories/base/base_spawn_events_repository.h index e9076136d..abf1e7573 100644 --- a/common/repositories/base/base_spawn_events_repository.h +++ b/common/repositories/base/base_spawn_events_repository.h @@ -267,7 +267,7 @@ public: insert_values.push_back(std::to_string(spawn_events_entry.argument)); insert_values.push_back(std::to_string(spawn_events_entry.strict)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_spawnentry_repository.h b/common/repositories/base/base_spawnentry_repository.h index e467d8397..8b00fe50c 100644 --- a/common/repositories/base/base_spawnentry_repository.h +++ b/common/repositories/base/base_spawnentry_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(spawnentry_entry.chance)); insert_values.push_back(std::to_string(spawnentry_entry.condition_value_filter)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_spawngroup_repository.h b/common/repositories/base/base_spawngroup_repository.h index a81509a35..62557ce2b 100644 --- a/common/repositories/base/base_spawngroup_repository.h +++ b/common/repositories/base/base_spawngroup_repository.h @@ -261,7 +261,7 @@ public: insert_values.push_back(std::to_string(spawngroup_entry.despawn_timer)); insert_values.push_back(std::to_string(spawngroup_entry.wp_spawns)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_spell_buckets_repository.h b/common/repositories/base/base_spell_buckets_repository.h index 4d0472fa8..b0c9abc52 100644 --- a/common/repositories/base/base_spell_buckets_repository.h +++ b/common/repositories/base/base_spell_buckets_repository.h @@ -203,7 +203,7 @@ public: insert_values.push_back("'" + EscapeString(spell_buckets_entry.key) + "'"); insert_values.push_back("'" + EscapeString(spell_buckets_entry.value) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_spell_globals_repository.h b/common/repositories/base/base_spell_globals_repository.h index c5936c51c..cc3a8e0d7 100644 --- a/common/repositories/base/base_spell_globals_repository.h +++ b/common/repositories/base/base_spell_globals_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back("'" + EscapeString(spell_globals_entry.qglobal) + "'"); insert_values.push_back("'" + EscapeString(spell_globals_entry.value) + "'"); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_spells_new_repository.h b/common/repositories/base/base_spells_new_repository.h index 8e54f1d52..f0930baf9 100644 --- a/common/repositories/base/base_spells_new_repository.h +++ b/common/repositories/base/base_spells_new_repository.h @@ -1607,7 +1607,7 @@ public: insert_values.push_back(std::to_string(spells_new_entry.field235)); insert_values.push_back(std::to_string(spells_new_entry.field236)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_start_zones_repository.h b/common/repositories/base/base_start_zones_repository.h index 7e8d8926a..347012500 100644 --- a/common/repositories/base/base_start_zones_repository.h +++ b/common/repositories/base/base_start_zones_repository.h @@ -299,7 +299,7 @@ public: insert_values.push_back("'" + EscapeString(start_zones_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(start_zones_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_starting_items_repository.h b/common/repositories/base/base_starting_items_repository.h index 4dca7a846..2a18b33e8 100644 --- a/common/repositories/base/base_starting_items_repository.h +++ b/common/repositories/base/base_starting_items_repository.h @@ -261,7 +261,7 @@ public: insert_values.push_back("'" + EscapeString(starting_items_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(starting_items_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_task_activities_repository.h b/common/repositories/base/base_task_activities_repository.h index c04b2b504..0bf3ca384 100644 --- a/common/repositories/base/base_task_activities_repository.h +++ b/common/repositories/base/base_task_activities_repository.h @@ -275,7 +275,7 @@ public: insert_values.push_back("'" + EscapeString(task_activities_entry.zones) + "'"); insert_values.push_back(std::to_string(task_activities_entry.optional)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_tasks_repository.h b/common/repositories/base/base_tasks_repository.h index 8091531aa..8c5aa3ff5 100644 --- a/common/repositories/base/base_tasks_repository.h +++ b/common/repositories/base/base_tasks_repository.h @@ -281,7 +281,7 @@ public: insert_values.push_back(std::to_string(tasks_entry.faction_reward)); insert_values.push_back("'" + EscapeString(tasks_entry.completion_emote) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_tasksets_repository.h b/common/repositories/base/base_tasksets_repository.h index 255d9bc81..a6fb2584a 100644 --- a/common/repositories/base/base_tasksets_repository.h +++ b/common/repositories/base/base_tasksets_repository.h @@ -197,7 +197,7 @@ public: insert_values.push_back(std::to_string(tasksets_entry.id)); insert_values.push_back(std::to_string(tasksets_entry.taskid)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_timers_repository.h b/common/repositories/base/base_timers_repository.h index 29f2d0c77..aff07d9b1 100644 --- a/common/repositories/base/base_timers_repository.h +++ b/common/repositories/base/base_timers_repository.h @@ -215,7 +215,7 @@ public: insert_values.push_back(std::to_string(timers_entry.duration)); insert_values.push_back(std::to_string(timers_entry.enable)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_titles_repository.h b/common/repositories/base/base_titles_repository.h index 00d63995c..d08374d2a 100644 --- a/common/repositories/base/base_titles_repository.h +++ b/common/repositories/base/base_titles_repository.h @@ -267,7 +267,7 @@ public: insert_values.push_back("'" + EscapeString(titles_entry.suffix) + "'"); insert_values.push_back(std::to_string(titles_entry.title_set)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_trader_repository.h b/common/repositories/base/base_trader_repository.h index bdd5f0d7a..330791e2b 100644 --- a/common/repositories/base/base_trader_repository.h +++ b/common/repositories/base/base_trader_repository.h @@ -221,7 +221,7 @@ public: insert_values.push_back(std::to_string(trader_entry.item_cost)); insert_values.push_back(std::to_string(trader_entry.slot_id)); - auto results = database.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_tradeskill_recipe_entries_repository.h b/common/repositories/base/base_tradeskill_recipe_entries_repository.h index 45c51af6a..d5a5351b7 100644 --- a/common/repositories/base/base_tradeskill_recipe_entries_repository.h +++ b/common/repositories/base/base_tradeskill_recipe_entries_repository.h @@ -231,7 +231,7 @@ public: insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.salvagecount)); insert_values.push_back(std::to_string(tradeskill_recipe_entries_entry.iscontainer)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_tradeskill_recipe_repository.h b/common/repositories/base/base_tradeskill_recipe_repository.h index 70855a17d..8156369c1 100644 --- a/common/repositories/base/base_tradeskill_recipe_repository.h +++ b/common/repositories/base/base_tradeskill_recipe_repository.h @@ -273,7 +273,7 @@ public: insert_values.push_back("'" + EscapeString(tradeskill_recipe_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(tradeskill_recipe_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_traps_repository.h b/common/repositories/base/base_traps_repository.h index 8047254e1..53e5883bd 100644 --- a/common/repositories/base/base_traps_repository.h +++ b/common/repositories/base/base_traps_repository.h @@ -333,7 +333,7 @@ public: insert_values.push_back("'" + EscapeString(traps_entry.content_flags) + "'"); insert_values.push_back("'" + EscapeString(traps_entry.content_flags_disabled) + "'"); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_tribute_levels_repository.h b/common/repositories/base/base_tribute_levels_repository.h index 99e7f816f..1754a10de 100644 --- a/common/repositories/base/base_tribute_levels_repository.h +++ b/common/repositories/base/base_tribute_levels_repository.h @@ -209,7 +209,7 @@ public: insert_values.push_back(std::to_string(tribute_levels_entry.cost)); insert_values.push_back(std::to_string(tribute_levels_entry.item_id)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_tributes_repository.h b/common/repositories/base/base_tributes_repository.h index 912124f0f..10da88ef5 100644 --- a/common/repositories/base/base_tributes_repository.h +++ b/common/repositories/base/base_tributes_repository.h @@ -215,7 +215,7 @@ public: insert_values.push_back("'" + EscapeString(tributes_entry.descr) + "'"); insert_values.push_back(std::to_string(tributes_entry.isguild)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_veteran_reward_templates_repository.h b/common/repositories/base/base_veteran_reward_templates_repository.h index 9a1cdd493..9a25e2b96 100644 --- a/common/repositories/base/base_veteran_reward_templates_repository.h +++ b/common/repositories/base/base_veteran_reward_templates_repository.h @@ -215,7 +215,7 @@ public: insert_values.push_back(std::to_string(veteran_reward_templates_entry.charges)); insert_values.push_back(std::to_string(veteran_reward_templates_entry.reward_slot)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_zone_points_repository.h b/common/repositories/base/base_zone_points_repository.h index 195f3330c..92cdaf7f8 100644 --- a/common/repositories/base/base_zone_points_repository.h +++ b/common/repositories/base/base_zone_points_repository.h @@ -327,7 +327,7 @@ public: insert_values.push_back(std::to_string(zone_points_entry.height)); insert_values.push_back(std::to_string(zone_points_entry.width)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/base/base_zone_repository.h b/common/repositories/base/base_zone_repository.h index fd174b96a..7e2066d42 100644 --- a/common/repositories/base/base_zone_repository.h +++ b/common/repositories/base/base_zone_repository.h @@ -729,7 +729,7 @@ public: insert_values.push_back("'" + EscapeString(zone_entry.content_flags_disabled) + "'"); insert_values.push_back(std::to_string(zone_entry.underworld_teleport_index)); - auto results = content_db.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/common/repositories/template/base_repository.template b/common/repositories/template/base_repository.template index 9227bede7..9bf695b1a 100644 --- a/common/repositories/template/base_repository.template +++ b/common/repositories/template/base_repository.template @@ -190,7 +190,7 @@ public: {{INSERT_ONE_ENTRIES}} - auto results = {{DATABASE_CONNECTION}}.QueryDatabase( + auto results = db.QueryDatabase( fmt::format( "{} VALUES ({})", BaseInsert(), diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 8d80e84c1..381123092 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -133,6 +133,10 @@ SET(zone_sources special_attacks.cpp spell_effects.cpp spells.cpp + task_client_state.cpp + task_goal_list_manager.cpp + task_manager.cpp + task_proximity_manager.cpp tasks.cpp titles.cpp tradeskills.cpp @@ -151,8 +155,7 @@ SET(zone_sources zonedb.cpp zone_reload.cpp zone_store.cpp - zoning.cpp -) + zoning.cpp) SET(zone_headers aa.h @@ -252,6 +255,10 @@ SET(zone_headers spawn2.h spawngroup.h string_ids.h + task_client_state.h + task_goal_list_manager.h + task_manager.h + task_proximity_manager.h tasks.h titles.h trap.h @@ -265,8 +272,7 @@ SET(zone_headers zonedb.h zonedump.h zone_reload.h - zone_store.h -) + zone_store.h) ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers}) diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 1dcebe5fc..10b869d9c 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -76,7 +76,7 @@ extern QueryServ* QServ; extern WorldServer worldserver; -extern TaskManager *taskmanager; +extern TaskManager *task_manager; void CatchSignal(int sig_num); diff --git a/zone/client.cpp b/zone/client.cpp index 1f1ab10b9..22bdb333e 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -258,7 +258,7 @@ Client::Client(EQStreamInterface* ieqs) tgb = false; tribute_master_id = 0xFFFFFFFF; tribute_timer.Disable(); - taskstate = nullptr; + task_state = nullptr; TotalSecondsPlayed = 0; keyring.clear(); bind_sight_target = nullptr; @@ -452,7 +452,7 @@ Client::~Client() { // will need this data right away Save(2); // This fails when database destructor is called first on shutdown - safe_delete(taskstate); + safe_delete(task_state); safe_delete(KarmaUpdateTimer); safe_delete(GlobalChatLimiterTimer); safe_delete(qGlobals); diff --git a/zone/client.h b/zone/client.h index cc461bc22..160ea145b 100644 --- a/zone/client.h +++ b/zone/client.h @@ -65,6 +65,8 @@ namespace EQ #include "zone.h" #include "zonedb.h" #include "zone_store.h" +#include "task_manager.h" +#include "task_client_state.h" #ifdef _WINDOWS // since windows defines these within windef.h (which windows.h include) @@ -86,7 +88,7 @@ namespace EQ #define XTARGET_HARDCAP 20 extern Zone* zone; -extern TaskManager *taskmanager; +extern TaskManager *task_manager; class CLIENTPACKET { @@ -1006,7 +1008,7 @@ public: uint32 GetSpellIDByBookSlot(int book_slot); int GetNextAvailableSpellBookSlot(int starting_slot = 0); inline uint32 GetSpellByBookSlot(int book_slot) { return m_pp.spell_book[book_slot]; } - inline bool HasSpellScribed(int spellid) { return (FindSpellBookSlotBySpellID(spellid) != -1 ? true : false); } + inline bool HasSpellScribed(int spellid) { return FindSpellBookSlotBySpellID(spellid) != -1; } uint16 GetMaxSkillAfterSpecializationRules(EQ::skills::SkillType skillid, uint16 maxSkill); void SendPopupToClient(const char *Title, const char *Text, uint32 PopupID = 0, uint32 Buttons = 0, uint32 Duration = 0); void SendFullPopup(const char *Title, const char *Text, uint32 PopupID = 0, uint32 NegativeID = 0, uint32 Buttons = 0, uint32 Duration = 0, const char *ButtonName0 = 0, const char *ButtonName1 = 0, uint32 SoundControls = 0); @@ -1021,48 +1023,241 @@ public: // Task System Methods void LoadClientTaskState(); void RemoveClientTaskState(); - void SendTaskActivityComplete(int TaskID, int ActivityID, int TaskIndex, TaskType type, int TaskIncomplete=1); - void SendTaskFailed(int TaskID, int TaskIndex, TaskType type); - void SendTaskComplete(int TaskIndex); - inline ClientTaskState *GetTaskState() const { return taskstate; } - - inline void CancelTask(int TaskIndex, TaskType type) { if(taskstate) taskstate->CancelTask(this, TaskIndex, type); } - inline bool SaveTaskState() { return (taskmanager ? taskmanager->SaveClientState(this, taskstate) : false); } - inline bool IsTaskStateLoaded() { return taskstate != nullptr; } - inline bool IsTaskActive(int TaskID) { return (taskstate ? taskstate->IsTaskActive(TaskID) : false); } - inline bool IsTaskActivityActive(int TaskID, int ActivityID) { return (taskstate ? taskstate->IsTaskActivityActive(TaskID, ActivityID) : false); } - inline ActivityState GetTaskActivityState(TaskType type, int index, int ActivityID) { return (taskstate ? taskstate->GetTaskActivityState(type, index, ActivityID) : ActivityHidden); } - inline void UpdateTaskActivity(int TaskID, int ActivityID, int Count, bool ignore_quest_update = false) { if (taskstate) taskstate->UpdateTaskActivity(this, TaskID, ActivityID, Count, ignore_quest_update); } - inline void RemoveTaskByTaskID(uint32 task_id) { if (taskstate) taskstate->RemoveTaskByTaskID(this, task_id); } - inline void ResetTaskActivity(int TaskID, int ActivityID) { if(taskstate) taskstate->ResetTaskActivity(this, TaskID, ActivityID); } - inline void UpdateTasksOnKill(int NPCTypeID) { if(taskstate) taskstate->UpdateTasksOnKill(this, NPCTypeID); } - inline void UpdateTasksForItem(ActivityType Type, int ItemID, int Count=1) { if(taskstate) taskstate->UpdateTasksForItem(this, Type, ItemID, Count); } - inline void UpdateTasksOnExplore(int ExploreID) { if(taskstate) taskstate->UpdateTasksOnExplore(this, ExploreID); } - inline bool UpdateTasksOnSpeakWith(int NPCTypeID) { if(taskstate) return taskstate->UpdateTasksOnSpeakWith(this, NPCTypeID); else return false; } - inline bool UpdateTasksOnDeliver(std::list& Items, int Cash, int NPCTypeID) { if (taskstate) return taskstate->UpdateTasksOnDeliver(this, Items, Cash, NPCTypeID); else return false; } - inline void TaskSetSelector(Mob *mob, int TaskSetID) { if(taskmanager) taskmanager->TaskSetSelector(this, taskstate, mob, TaskSetID); } - inline void TaskQuestSetSelector(Mob *mob, int count, int *tasks) { if(taskmanager) taskmanager->TaskQuestSetSelector(this, taskstate, mob, count, tasks); } - inline void EnableTask(int TaskCount, int *TaskList) { if(taskstate) taskstate->EnableTask(CharacterID(), TaskCount, TaskList); } - inline void DisableTask(int TaskCount, int *TaskList) { if(taskstate) taskstate->DisableTask(CharacterID(), TaskCount, TaskList); } - inline bool IsTaskEnabled(int TaskID) { return (taskstate ? taskstate->IsTaskEnabled(TaskID) : false); } - inline void ProcessTaskProximities(float X, float Y, float Z) { if(taskstate) taskstate->ProcessTaskProximities(this, X, Y, Z); } - inline void AssignTask(int TaskID, int NPCID, bool enforce_level_requirement = false) { if (taskstate) taskstate->AcceptNewTask(this, TaskID, NPCID, enforce_level_requirement); } - inline int ActiveSpeakTask(int NPCID) { if(taskstate) return taskstate->ActiveSpeakTask(NPCID); else return 0; } - inline int ActiveSpeakActivity(int NPCID, int TaskID) { if(taskstate) return taskstate->ActiveSpeakActivity(NPCID, TaskID); else return 0; } - inline void FailTask(int TaskID) { if(taskstate) taskstate->FailTask(this, TaskID); } - inline int TaskTimeLeft(int TaskID) { return (taskstate ? taskstate->TaskTimeLeft(TaskID) : 0); } - inline int EnabledTaskCount(int TaskSetID) { return (taskstate ? taskstate->EnabledTaskCount(TaskSetID) : -1); } - inline int IsTaskCompleted(int TaskID) { return (taskstate ? taskstate->IsTaskCompleted(TaskID) : -1); } - inline void ShowClientTasks() { if(taskstate) taskstate->ShowClientTasks(this); } - inline void CancelAllTasks() { if(taskstate) taskstate->CancelAllTasks(this); } - inline int GetActiveTaskCount() { return (taskstate ? taskstate->GetActiveTaskCount() : 0); } - inline int GetActiveTaskID(int index) { return (taskstate ? taskstate->GetActiveTaskID(index) : -1); } - inline int GetTaskStartTime(TaskType type, int index) { return (taskstate ? taskstate->GetTaskStartTime(type, index) : -1); } - inline bool IsTaskActivityCompleted(TaskType type, int index, int ActivityID) { return (taskstate ? taskstate->IsTaskActivityCompleted(type, index, ActivityID) : false); } - inline int GetTaskActivityDoneCount(TaskType type, int ClientTaskIndex, int ActivityID) { return (taskstate ? taskstate->GetTaskActivityDoneCount(type, ClientTaskIndex, ActivityID) :0); } - inline int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID) { return (taskstate ? taskstate->GetTaskActivityDoneCountFromTaskID(TaskID, ActivityID) :0); } - inline int ActiveTasksInSet(int TaskSet) { return (taskstate ? taskstate->ActiveTasksInSet(TaskSet) :0); } - inline int CompletedTasksInSet(int TaskSet) { return (taskstate ? taskstate->CompletedTasksInSet(TaskSet) :0); } + void SendTaskActivityComplete(int task_id, int activity_id, int task_index, TaskType task_type, int task_incomplete=1); + void SendTaskFailed(int task_id, int task_index, TaskType task_type); + void SendTaskComplete(int task_index); + inline ClientTaskState *GetTaskState() const { return task_state; } + inline void CancelTask(int task_index, TaskType task_type) + { + if (task_state) { + task_state->CancelTask( + this, + task_index, + task_type + ); + } + } + inline bool SaveTaskState() + { + return task_manager != nullptr && task_manager->SaveClientState(this, task_state); + } + inline bool IsTaskStateLoaded() { return task_state != nullptr; } + inline bool IsTaskActive(int task_id) { return task_state != nullptr && task_state->IsTaskActive(task_id); } + inline bool IsTaskActivityActive(int task_id, int activity_id) + { + return task_state != nullptr && + task_state->IsTaskActivityActive( + task_id, + activity_id + ); + } + inline ActivityState GetTaskActivityState(TaskType task_type, int index, int activity_id) + { + return (task_state ? task_state->GetTaskActivityState(task_type, index, activity_id) : ActivityHidden); + } + inline void UpdateTaskActivity( + int task_id, + int activity_id, + int count, + bool ignore_quest_update = false + ) + { + if (task_state) { + task_state->UpdateTaskActivity(this, task_id, activity_id, count, ignore_quest_update); + } + } + inline void RemoveTaskByTaskID(uint32 task_id) { + if (task_state) { + task_state->RemoveTaskByTaskID(this, task_id); + } + } + inline void ResetTaskActivity(int task_id, int activity_id) + { + if (task_state) { + task_state->ResetTaskActivity( + this, + task_id, + activity_id + ); + } + } + inline void UpdateTasksOnKill(int npc_type_id) + { + if (task_state) { + task_state->UpdateTasksOnKill( + this, + npc_type_id + ); + } + } + inline void UpdateTasksForItem( + ActivityType activity_type, + int item_id, + int count = 1 + ) + { + if (task_state) { + task_state->UpdateTasksForItem(this, activity_type, item_id, count); + } + } + inline void UpdateTasksOnExplore(int explore_id) + { + if (task_state) { + task_state->UpdateTasksOnExplore( + this, + explore_id + ); + } + } + inline bool UpdateTasksOnSpeakWith(int npc_type_id) + { + if (task_state) { + return task_state->UpdateTasksOnSpeakWith( + this, + npc_type_id + ); + } + else { return false; } + } + inline bool UpdateTasksOnDeliver( + std::list &items, + int cash, + int npc_type_id + ) + { + if (task_state) { + return task_state->UpdateTasksOnDeliver( + this, + items, + cash, + npc_type_id + ); + } + else { return false; } + } + inline void TaskSetSelector(Mob *mob, int task_set_id) + { + if (task_manager) { + task_manager->TaskSetSelector( + this, + task_state, + mob, + task_set_id + ); + } + } + inline void TaskQuestSetSelector(Mob *mob, int count, int *tasks) + { + if (task_manager) { + task_manager->TaskQuestSetSelector( + this, + task_state, + mob, + count, + tasks + ); + } + } + inline void EnableTask(int task_count, int *task_list) + { + if (task_state) { + task_state->EnableTask( + CharacterID(), + task_count, + task_list + ); + } + } + inline void DisableTask(int task_count, int *task_list) + { + if (task_state) { + task_state->DisableTask( + CharacterID(), + task_count, + task_list + ); + } + } + inline bool IsTaskEnabled(int task_id) { + return task_state != nullptr && task_state->IsTaskEnabled(task_id); + } + inline void ProcessTaskProximities(float x, float y, float z) + { + if (task_state) { + task_state->ProcessTaskProximities( + this, + x, + y, + z + ); + } + } + inline void AssignTask( + int task_id, + int npc_id, + bool enforce_level_requirement = false + ) { + if (task_state) { + task_state->AcceptNewTask(this, task_id, npc_id, enforce_level_requirement); + } + } + inline int ActiveSpeakTask(int npc_type_id) + { + if (task_state) { + return task_state->ActiveSpeakTask(npc_type_id); + } + else { + return 0; + } + } + inline int ActiveSpeakActivity(int npc_type_id, int task_id) + { + if (task_state) { + return task_state->ActiveSpeakActivity( + npc_type_id, + task_id + ); + } + else { return 0; } + } + inline void FailTask(int task_id) { if (task_state) { task_state->FailTask(this, task_id); }} + inline int TaskTimeLeft(int task_id) { return (task_state ? task_state->TaskTimeLeft(task_id) : 0); } + inline int EnabledTaskCount(int task_set_id) + { + return (task_state ? task_state->EnabledTaskCount(task_set_id) : -1); + } + inline int IsTaskCompleted(int task_id) { return (task_state ? task_state->IsTaskCompleted(task_id) : -1); } + inline void ShowClientTasks(Client *client) { if (task_state) { task_state->ShowClientTasks(client); }} + inline void CancelAllTasks() { if (task_state) { task_state->CancelAllTasks(this); }} + inline int GetActiveTaskCount() { return (task_state ? task_state->GetActiveTaskCount() : 0); } + inline int GetActiveTaskID(int index) { return (task_state ? task_state->GetActiveTaskID(index) : -1); } + inline int GetTaskStartTime(TaskType task_type, int index) + { + return (task_state ? task_state->GetTaskStartTime( + task_type, + index + ) : -1); + } + inline bool IsTaskActivityCompleted(TaskType task_type, int index, int activity_id) + { + return task_state != nullptr && task_state->IsTaskActivityCompleted(task_type, index, activity_id); + } + inline int GetTaskActivityDoneCount(TaskType task_type, int client_task_index, int activity_id) + { + return (task_state ? task_state->GetTaskActivityDoneCount(task_type, client_task_index, activity_id) : 0); + } + inline int GetTaskActivityDoneCountFromTaskID(int task_id, int activity_id) + { + return (task_state ? task_state->GetTaskActivityDoneCountFromTaskID(task_id, activity_id) : 0); + } + inline int ActiveTasksInSet(int task_set_id) + { + return (task_state ? task_state->ActiveTasksInSet(task_set_id) : 0); + } + inline int CompletedTasksInSet(int task_set_id) + { + return (task_state ? task_state->CompletedTasksInSet(task_set_id) : 0); + } inline const EQ::versions::ClientVersion ClientVersion() const { return m_ClientVersion; } inline const uint32 ClientVersionBit() const { return m_ClientVersionBit; } @@ -1645,7 +1840,7 @@ private: std::set zone_flags; - ClientTaskState *taskstate; + ClientTaskState *task_state; int TotalSecondsPlayed; //Anti Spam Stuff diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 12df5cb0e..8ce8057a5 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1821,8 +1821,8 @@ void Client::Handle_OP_AcceptNewTask(const EQApplicationPacket *app) } AcceptNewTask_Struct *ant = (AcceptNewTask_Struct*)app->pBuffer; - if (ant->task_id > 0 && RuleB(TaskSystem, EnableTaskSystem) && taskstate) - taskstate->AcceptNewTask(this, ant->task_id, ant->task_master_id); + if (ant->task_id > 0 && RuleB(TaskSystem, EnableTaskSystem) && task_state) + task_state->AcceptNewTask(this, ant->task_id, ant->task_master_id); } void Client::Handle_OP_AdventureInfoRequest(const EQApplicationPacket *app) @@ -4004,8 +4004,8 @@ void Client::Handle_OP_CancelTask(const EQApplicationPacket *app) } CancelTask_Struct *cts = (CancelTask_Struct*)app->pBuffer; - if (RuleB(TaskSystem, EnableTaskSystem) && taskstate) - taskstate->CancelTask(this, cts->SequenceNumber, static_cast(cts->type)); + if (RuleB(TaskSystem, EnableTaskSystem) && task_state) + task_state->CancelTask(this, cts->SequenceNumber, static_cast(cts->type)); } void Client::Handle_OP_CancelTrade(const EQApplicationPacket *app) @@ -13996,8 +13996,8 @@ void Client::Handle_OP_TaskHistoryRequest(const EQApplicationPacket *app) } TaskHistoryRequest_Struct *ths = (TaskHistoryRequest_Struct*)app->pBuffer; - if (RuleB(TaskSystem, EnableTaskSystem) && taskstate) - taskstate->SendTaskHistory(this, ths->TaskIndex); + if (RuleB(TaskSystem, EnableTaskSystem) && task_state) + task_state->SendTaskHistory(this, ths->TaskIndex); } void Client::Handle_OP_Taunt(const EQApplicationPacket *app) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 15dfa160f..fd8a6cb02 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -158,8 +158,8 @@ bool Client::Process() { CalcItemScale(); } - if (TaskPeriodic_Timer.Check() && taskstate) - taskstate->TaskPeriodicChecks(this); + if (TaskPeriodic_Timer.Check() && task_state) + task_state->TaskPeriodicChecks(this); if (dynamiczone_removal_timer.Check() && zone && zone->GetInstanceID() != 0) { diff --git a/zone/command.cpp b/zone/command.cpp index c156d4331..b88f1e102 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -77,7 +77,7 @@ extern QueryServ* QServ; extern WorldServer worldserver; -extern TaskManager *taskmanager; +extern TaskManager *task_manager; extern FastMath g_Math; void CatchSignal(int sig_num); @@ -10169,76 +10169,135 @@ void command_rules(Client *c, const Seperator *sep) { void command_task(Client *c, const Seperator *sep) { //super-command for managing tasks if(sep->arg[1][0] == '\0' || !strcasecmp(sep->arg[1], "help")) { - c->Message(Chat::White, "Syntax: #task [subcommand]."); - c->Message(Chat::White, "-- Task System Commands --"); - c->Message(Chat::White, "...show - List active tasks for a client"); - c->Message(Chat::White, "...update [Count]"); - c->Message(Chat::White, "...reloadall - Reload all Task information from the database"); - c->Message(Chat::White, "...reload task - Reload Task and Activity informnation for a single task"); - c->Message(Chat::White, "...reload lists - Reload goal/reward list information"); - c->Message(Chat::White, "...reload prox - Reload proximity information"); - c->Message(Chat::White, "...reload sets - Reload task set information"); + c->Message(Chat::White, "Syntax: #task [subcommand]"); + c->Message(Chat::White, "------------------------------------------------"); + c->Message(Chat::White, "# Task System Commands"); + c->Message(Chat::White, "------------------------------------------------"); + c->Message( + Chat::White, + fmt::format( + "--- [{}] List active tasks for a client", + EQ::SayLinkEngine::GenerateQuestSaylink("#task show", false, "show") + ).c_str() + ); + c->Message(Chat::White, "--- update [count] | Updates task"); + c->Message(Chat::White, "--- assign | Assigns task to client"); + c->Message( + Chat::White, + fmt::format( + "--- [{}] Reload all Task information from the database", + EQ::SayLinkEngine::GenerateQuestSaylink("#task reloadall", false, "reloadall") + ).c_str() + ); + c->Message( + Chat::White, + fmt::format( + "--- [{}] Reload Task and Activity information for a single task", + EQ::SayLinkEngine::GenerateQuestSaylink("#task reload task", false, "reload task") + ).c_str() + ); + c->Message( + Chat::White, + fmt::format( + "--- [{}] Reload goal/reward list information", + EQ::SayLinkEngine::GenerateQuestSaylink("#task reload lists", false, "reload lists") + ).c_str() + ); + c->Message( + Chat::White, + fmt::format( + "--- [{}] Reload proximity information", + EQ::SayLinkEngine::GenerateQuestSaylink("#task reload prox", false, "reload prox") + ).c_str() + ); + c->Message( + Chat::White, + fmt::format( + "--- [{}] Reload task set information", + EQ::SayLinkEngine::GenerateQuestSaylink("#task reload sets", false, "reload sets") + ).c_str() + ); return; } - if(!strcasecmp(sep->arg[1], "show")) { - if(c->GetTarget() && c->GetTarget()->IsClient()) - c->GetTarget()->CastToClient()->ShowClientTasks(); - else - c->ShowClientTasks(); + Client *client_target = c; + if (c->GetTarget() && c->GetTarget()->IsClient()) { + client_target = c->GetTarget()->CastToClient(); + } + if (!strcasecmp(sep->arg[1], "show")) { + c->ShowClientTasks(client_target); return; } - if(!strcasecmp(sep->arg[1], "update")) { - if(sep->argnum>=3) { - int TaskID = atoi(sep->arg[2]); - int ActivityID = atoi(sep->arg[3]); - int Count=1; + if (!strcasecmp(sep->arg[1], "update")) { + if (sep->argnum >= 3) { + int task_id = atoi(sep->arg[2]); + int activity_id = atoi(sep->arg[3]); + int count = 1; - if(sep->argnum>=4) { - Count = atoi(sep->arg[4]); - if(Count <= 0) - Count = 1; + if (sep->argnum >= 4) { + count = atoi(sep->arg[4]); + if (count <= 0) { + count = 1; + } } - c->Message(Chat::Yellow, "Updating Task %i, Activity %i, Count %i", TaskID, ActivityID, Count); - c->UpdateTaskActivity(TaskID, ActivityID, Count); + c->Message( + Chat::Yellow, + "Updating Task [%i] Activity [%i] Count [%i] for client [%s]", + task_id, + activity_id, + count, + client_target->GetCleanName() + ); + client_target->UpdateTaskActivity(task_id, activity_id, count); + c->ShowClientTasks(client_target); } return; } - if(!strcasecmp(sep->arg[1], "reloadall")) { + + if (!strcasecmp(sep->arg[1], "assign")) { + int task_id = atoi(sep->arg[2]); + if ((task_id > 0) && (task_id < MAXTASKS)) { + client_target->AssignTask(task_id, 0, false); + c->Message(Chat::Yellow, "Assigned task [%i] to [%s]", task_id, client_target->GetCleanName()); + } + return; + } + + if (!strcasecmp(sep->arg[1], "reloadall")) { c->Message(Chat::Yellow, "Sending reloadtasks to world"); worldserver.SendReloadTasks(RELOADTASKS); c->Message(Chat::Yellow, "Back again"); return; } - if(!strcasecmp(sep->arg[1], "reload")) { - if(sep->arg[2][0] != '\0') { - if(!strcasecmp(sep->arg[2], "lists")) { + if (!strcasecmp(sep->arg[1], "reload")) { + if (sep->arg[2][0] != '\0') { + if (!strcasecmp(sep->arg[2], "lists")) { c->Message(Chat::Yellow, "Sending reload lists to world"); worldserver.SendReloadTasks(RELOADTASKGOALLISTS); - c->Message(Chat::Yellow, "Back again"); + c->Message(Chat::Yellow, "Reloaded"); return; } - if(!strcasecmp(sep->arg[2], "prox")) { + if (!strcasecmp(sep->arg[2], "prox")) { c->Message(Chat::Yellow, "Sending reload proximities to world"); worldserver.SendReloadTasks(RELOADTASKPROXIMITIES); - c->Message(Chat::Yellow, "Back again"); + c->Message(Chat::Yellow, "Reloaded"); return; } - if(!strcasecmp(sep->arg[2], "sets")) { + if (!strcasecmp(sep->arg[2], "sets")) { c->Message(Chat::Yellow, "Sending reload task sets to world"); worldserver.SendReloadTasks(RELOADTASKSETS); - c->Message(Chat::Yellow, "Back again"); + c->Message(Chat::Yellow, "Reloaded"); return; } - if(!strcasecmp(sep->arg[2], "task") && (sep->arg[3][0] != '\0')) { - int TaskID = atoi(sep->arg[3]); - if((TaskID > 0) && (TaskID < MAXTASKS)) { - c->Message(Chat::Yellow, "Sending reload task %i to world", TaskID); - worldserver.SendReloadTasks(RELOADTASKS, TaskID); - c->Message(Chat::Yellow, "Back again"); + if (!strcasecmp(sep->arg[2], "task") && (sep->arg[3][0] != '\0')) { + int task_id = atoi(sep->arg[3]); + if ((task_id > 0) && (task_id < MAXTASKS)) { + c->Message(Chat::Yellow, "Sending reload task %i to world", task_id); + worldserver.SendReloadTasks(RELOADTASKS, task_id); + c->Message(Chat::Yellow, "Reloaded"); return; } } diff --git a/zone/entity.cpp b/zone/entity.cpp index f48b371ce..dc630ceef 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -32,6 +32,7 @@ #include "../common/features.h" #include "../common/guilds.h" +#include "entity.h" #include "dynamiczone.h" #include "guild_mgr.h" #include "petitions.h" @@ -3900,22 +3901,24 @@ void EntityList::ProcessProximitySay(const char *Message, Client *c, uint8 langu void EntityList::SaveAllClientsTaskState() { - if (!taskmanager) + if (!task_manager) { return; + } auto it = client_list.begin(); while (it != client_list.end()) { Client *client = it->second; - if (client->IsTaskStateLoaded()) + if (client->IsTaskStateLoaded()) { client->SaveTaskState(); + } ++it; } } -void EntityList::ReloadAllClientsTaskState(int TaskID) +void EntityList::ReloadAllClientsTaskState(int task_id) { - if (!taskmanager) + if (!task_manager) return; auto it = client_list.begin(); @@ -3924,11 +3927,11 @@ void EntityList::ReloadAllClientsTaskState(int TaskID) if (client->IsTaskStateLoaded()) { // If we have been passed a TaskID, only reload the client state if they have // that Task active. - if ((!TaskID) || (TaskID && client->IsTaskActive(TaskID))) { + if ((!task_id) || (task_id && client->IsTaskActive(task_id))) { Log(Logs::General, Logs::Tasks, "[CLIENTLOAD] Reloading Task State For Client %s", client->GetName()); client->RemoveClientTaskState(); client->LoadClientTaskState(); - taskmanager->SendActiveTasksToClient(client); + task_manager->SendActiveTasksToClient(client); } } ++it; @@ -4136,7 +4139,7 @@ void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy) if (n->GetSwarmInfo()) { if (n->GetSwarmInfo()->owner_id == owner->GetID()) { if ( - !n->GetSpecialAbility(IMMUNE_AGGRO) && + !n->GetSpecialAbility(IMMUNE_AGGRO) && !(n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient()) && !(n->GetSpecialAbility(IMMUNE_AGGRO_NPC) && other->IsNPC()) ) { diff --git a/zone/entity.h b/zone/entity.h index 5bb5981fa..5a93adf9d 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -483,7 +483,7 @@ public: void SendGroupLeader(uint32 gid, const char *lname, const char *oldlname); void SaveAllClientsTaskState(); - void ReloadAllClientsTaskState(int TaskID=0); + void ReloadAllClientsTaskState(int task_id=0); uint16 CreateGroundObject(uint32 itemid, const glm::vec4& position, uint32 decay_time = 300000); uint16 CreateGroundObjectFromModel(const char *model, const glm::vec4& position, uint8 type = 0x00, uint32 decay_time = 0); uint16 CreateDoor(const char *model, const glm::vec4& position, uint8 type = 0, uint16 size = 100); diff --git a/zone/main.cpp b/zone/main.cpp index 7b5fca736..376b8a508 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -22,26 +22,18 @@ #define PLATFORM_ZONE 1 #include "../common/global_define.h" -#include "../common/features.h" -#include "../common/queue.h" #include "../common/timer.h" #include "../common/eq_packet_structs.h" #include "../common/mutex.h" -#include "../common/version.h" -#include "../common/packet_dump_file.h" #include "../common/opcodemgr.h" #include "../common/guilds.h" #include "../common/eq_stream_ident.h" #include "../common/patches/patches.h" #include "../common/rulesys.h" #include "../common/profanity_manager.h" -#include "../common/misc_functions.h" #include "../common/string_util.h" -#include "../common/platform.h" #include "../common/crash.h" -#include "../common/ipc_mutex.h" #include "../common/memory_mapped_file.h" -#include "../common/eqemu_exception.h" #include "../common/spdat.h" #include "../common/eqemu_logsys.h" @@ -57,32 +49,21 @@ #endif #include "zonedb.h" #include "zone_store.h" -#include "zone_config.h" #include "titles.h" #include "guild_mgr.h" -#include "tasks.h" +#include "task_manager.h" #include "quest_parser_collection.h" #include "embparser.h" #include "lua_parser.h" #include "questmgr.h" #include "npc_scale_manager.h" -#include "../common/event/event_loop.h" -#include "../common/event/timer.h" #include "../common/net/eqstream.h" -#include "../common/net/servertalk_server.h" #include "../common/content/world_content_service.h" -#include "../common/repositories/content_flags_repository.h" -#include -#include -#include #include -#include #include #include -#include -#include #include #ifdef _CRTDBG_MAP_ALLOC @@ -115,8 +96,8 @@ char errorname[32]; extern Zone* zone; npcDecayTimes_Struct npcCorpseDecayTimes[100]; TitleManager title_manager; -QueryServ *QServ = 0; -TaskManager *taskmanager = 0; +QueryServ *QServ = 0; +TaskManager *task_manager = 0; NpcScaleManager *npc_scale_manager; QuestParserCollection *parse = 0; EQEmuLogSys LogSys; @@ -426,9 +407,8 @@ int main(int argc, char** argv) { #endif if (RuleB(TaskSystem, EnableTaskSystem)) { - Log(Logs::General, Logs::Tasks, "[INIT] Loading Tasks"); - taskmanager = new TaskManager; - taskmanager->LoadTasks(); + task_manager = new TaskManager; + task_manager->LoadTasks(); } parse = new QuestParserCollection(); @@ -607,7 +587,7 @@ int main(int argc, char** argv) { if (zone != 0) Zone::Shutdown(true); //Fix for Linux world server problem. - safe_delete(taskmanager); + safe_delete(task_manager); command_deinit(); #ifdef BOTS bot_command_deinit(); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index f164341f8..a61a4e856 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2223,27 +2223,27 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level void QuestManager::taskselector(int taskcount, int *tasks) { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && taskmanager) + if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && task_manager) initiator->TaskQuestSetSelector(owner, taskcount, tasks); } void QuestManager::enabletask(int taskcount, int *tasks) { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && initiator && taskmanager) + if(RuleB(TaskSystem, EnableTaskSystem) && initiator && task_manager) initiator->EnableTask(taskcount, tasks); } void QuestManager::disabletask(int taskcount, int *tasks) { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && initiator && taskmanager) + if(RuleB(TaskSystem, EnableTaskSystem) && initiator && task_manager) initiator->DisableTask(taskcount, tasks); } bool QuestManager::istaskenabled(int taskid) { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && initiator && taskmanager) + if(RuleB(TaskSystem, EnableTaskSystem) && initiator && task_manager) return initiator->IsTaskEnabled(taskid); return false; @@ -2252,7 +2252,7 @@ bool QuestManager::istaskenabled(int taskid) { void QuestManager::tasksetselector(int tasksetid) { QuestManagerCurrentQuestVars(); Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSetSelector called for task set %i", tasksetid); - if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && taskmanager) + if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && task_manager) initiator->TaskSetSelector(owner, tasksetid); } @@ -2341,8 +2341,8 @@ int QuestManager::enabledtaskcount(int taskset) { int QuestManager::firsttaskinset(int taskset) { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && taskmanager) - return taskmanager->FirstTaskInSet(taskset); + if(RuleB(TaskSystem, EnableTaskSystem) && task_manager) + return task_manager->FirstTaskInSet(taskset); return -1; } @@ -2350,8 +2350,8 @@ int QuestManager::firsttaskinset(int taskset) { int QuestManager::lasttaskinset(int taskset) { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && taskmanager) - return taskmanager->LastTaskInSet(taskset); + if(RuleB(TaskSystem, EnableTaskSystem) && task_manager) + return task_manager->LastTaskInSet(taskset); return -1; } @@ -2359,8 +2359,8 @@ int QuestManager::lasttaskinset(int taskset) { int QuestManager::nexttaskinset(int taskset, int taskid) { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && taskmanager) - return taskmanager->NextTaskInSet(taskset, taskid); + if(RuleB(TaskSystem, EnableTaskSystem) && task_manager) + return task_manager->NextTaskInSet(taskset, taskid); return -1; } @@ -2412,8 +2412,8 @@ int QuestManager::completedtasksinset(int taskset) { bool QuestManager::istaskappropriate(int task) { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && initiator && taskmanager) - return taskmanager->AppropriateLevel(task, initiator->GetLevel()); + if(RuleB(TaskSystem, EnableTaskSystem) && initiator && task_manager) + return task_manager->ValidateLevel(task, initiator->GetLevel()); return false; } @@ -2422,7 +2422,7 @@ std::string QuestManager::gettaskname(uint32 task_id) { QuestManagerCurrentQuestVars(); if (RuleB(TaskSystem, EnableTaskSystem)) { - return taskmanager->GetTaskName(task_id); + return task_manager->GetTaskName(task_id); } return std::string(); diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp new file mode 100644 index 000000000..3ded9eb27 --- /dev/null +++ b/zone/task_client_state.cpp @@ -0,0 +1,2177 @@ +#include "../common/global_define.h" +#include "../common/misc_functions.h" +#include "../common/repositories/character_activities_repository.h" +#include "../common/repositories/character_tasks_repository.h" +#include "../common/repositories/completed_tasks_repository.h" +#include "../common/rulesys.h" +#include "client.h" +#include "queryserv.h" +#include "quest_parser_collection.h" +#include "task_client_state.h" +#include "zonedb.h" + +extern QueryServ *QServ; + +ClientTaskState::ClientTaskState() +{ + m_active_task_count = 0; + m_last_completed_task_loaded = 0; + m_checked_touch_activities = false; + + for (int i = 0; i < MAXACTIVEQUESTS; i++) { + m_active_quests[i].slot = i; + m_active_quests[i].task_id = TASKSLOTEMPTY; + } + + m_active_task.slot = 0; + m_active_task.task_id = TASKSLOTEMPTY; + // TODO: shared task +} + +ClientTaskState::~ClientTaskState() +{ +} + +void ClientTaskState::SendTaskHistory(Client *client, int task_index) +{ + + LogTasks("[SendTaskHistory] Task history requested for completed task index [{}]", task_index); + + // We only sent the most recent 50 completed tasks, so we need to offset the Index the client sent to us. + + int adjusted_task_index = task_index; + if (m_completed_tasks.size() > 50) { + adjusted_task_index += (m_completed_tasks.size() - 50); + } + + if ((adjusted_task_index < 0) || (adjusted_task_index >= (int) m_completed_tasks.size())) { + return; + } + + int task_id = m_completed_tasks[adjusted_task_index].task_id; + if ((task_id < 0) || (task_id > MAXTASKS)) { + return; + } + + TaskInformation *p_task_data = task_manager->m_task_data[task_id]; + + if (p_task_data == nullptr) { + return; + } + + TaskHistoryReplyHeader_Struct *task_history_reply; + TaskHistoryReplyData1_Struct *task_history_reply_data_1; + TaskHistoryReplyData2_Struct *task_history_reply_data_2; + + char *reply; + + int completed_activity_count = 0; + int packet_length = sizeof(TaskHistoryReplyHeader_Struct); + + for (int i = 0; i < p_task_data->activity_count; i++) { + if (m_completed_tasks[adjusted_task_index].activity_done[i]) { + completed_activity_count++; + packet_length = packet_length + sizeof(TaskHistoryReplyData1_Struct) + + p_task_data->activity_information[i].target_name.size() + 1 + + p_task_data->activity_information[i].item_list.size() + 1 + + sizeof(TaskHistoryReplyData2_Struct) + + p_task_data->activity_information[i].description_override.size() + 1; + } + } + + auto outapp = new EQApplicationPacket(OP_TaskHistoryReply, packet_length); + + task_history_reply = (TaskHistoryReplyHeader_Struct *) outapp->pBuffer; + + // We use the TaskIndex the client sent in the request + task_history_reply->TaskID = task_index; + task_history_reply->ActivityCount = completed_activity_count; + + reply = (char *) task_history_reply + sizeof(TaskHistoryReplyHeader_Struct); + + for (int i = 0; i < p_task_data->activity_count; i++) { + if (m_completed_tasks[adjusted_task_index].activity_done[i]) { + task_history_reply_data_1 = (TaskHistoryReplyData1_Struct *) reply; + task_history_reply_data_1->ActivityType = p_task_data->activity_information[i].activity_type; + reply = (char *) task_history_reply_data_1 + sizeof(TaskHistoryReplyData1_Struct); + VARSTRUCT_ENCODE_STRING(reply, p_task_data->activity_information[i].target_name.c_str()); + VARSTRUCT_ENCODE_STRING(reply, p_task_data->activity_information[i].item_list.c_str()); + task_history_reply_data_2 = (TaskHistoryReplyData2_Struct *) reply; + task_history_reply_data_2->GoalCount = p_task_data->activity_information[i].goal_count; + task_history_reply_data_2->unknown04 = 0xffffffff; + task_history_reply_data_2->unknown08 = 0xffffffff; + task_history_reply_data_2->ZoneID = p_task_data->activity_information[i].zone_ids.empty() ? 0 + : p_task_data->activity_information[i].zone_ids.front(); + task_history_reply_data_2->unknown16 = 0x00000000; + reply = (char *) task_history_reply_data_2 + sizeof(TaskHistoryReplyData2_Struct); + VARSTRUCT_ENCODE_STRING(reply, p_task_data->activity_information[i].description_override.c_str()); + } + } + + client->QueuePacket(outapp); + safe_delete(outapp); +} + +void ClientTaskState::EnableTask(int character_id, int task_count, int *task_list) +{ + // Check if the Task is already enabled for this client + std::vector tasks_enabled; + + for (int i = 0; i < task_count; i++) { + auto iterator = m_enabled_tasks.begin(); + bool add_task = true; + + while (iterator != m_enabled_tasks.end()) { + // If this task is already enabled, stop looking + if ((*iterator) == task_list[i]) { + add_task = false; + break; + } + // Our list of enabled tasks is sorted, so we can quit if we find a taskid higher than + // the one we are looking for. + if ((*iterator) > task_list[i]) { + break; + } + ++iterator; + } + + if (add_task) { + m_enabled_tasks.insert(iterator, task_list[i]); + // Make a note of the task we enabled, for later SQL generation + tasks_enabled.push_back(task_list[i]); + } + } + + LogTasksDetail("[EnableTask] New enabled task list"); + for (int enabled_task : m_enabled_tasks) { + LogTasksDetail("[EnableTask] enabled [{}] character_id [{}]", enabled_task, character_id); + } + + if (tasks_enabled.empty()) { + return; + } + + std::stringstream query_stream; + query_stream << "REPLACE INTO character_enabledtasks (charid, taskid) VALUES "; + for (unsigned int i = 0; i < tasks_enabled.size(); i++) { + query_stream << (i ? ", " : "") << StringFormat("(%i, %i)", character_id, tasks_enabled[i]); + } + + std::string query = query_stream.str(); + if (!tasks_enabled.empty()) { + database.QueryDatabase(query); + } + else { + LogTasks("[EnableTask] Called for character_id [{}] but, no tasks exist", character_id); + } +} + +void ClientTaskState::DisableTask(int character_id, int task_count, int *task_list) +{ + + // Check if the Task is enabled for this client + std::vector tasks_disabled; + + for (int task_id = 0; task_id < task_count; task_id++) { + auto iterator = m_enabled_tasks.begin(); + bool removeTask = false; + + while (iterator != m_enabled_tasks.end()) { + if ((*iterator) == task_list[task_id]) { + removeTask = true; + break; + } + + if ((*iterator) > task_list[task_id]) { + break; + } + + ++iterator; + } + + if (removeTask) { + m_enabled_tasks.erase(iterator); + tasks_disabled.push_back(task_list[task_id]); + } + } + + LogTasks("[DisableTask] New enabled task list "); + for (int enabled_task : m_enabled_tasks) { + LogTasks("[DisableTask] enabled_tasks [{}]", enabled_task); + } + + if (tasks_disabled.empty()) { + return; + } + + std::stringstream queryStream; + queryStream << StringFormat("DELETE FROM character_enabledtasks WHERE charid = %i AND (", character_id); + + for (unsigned int i = 0; i < tasks_disabled.size(); i++) + queryStream + << (i ? StringFormat("taskid = %i ", tasks_disabled[i]) : StringFormat( + "OR taskid = %i ", + tasks_disabled[i] + )); + + queryStream << ")"; + + std::string query = queryStream.str(); + + if (tasks_disabled.size()) { + database.QueryDatabase(query); + } + else { + LogTasks( + "[DisableTask] DisableTask called for character_id [{}] ... but, no tasks exist", + character_id + ); + } +} + +bool ClientTaskState::IsTaskEnabled(int task_id) +{ + std::vector::iterator iterator; + + iterator = m_enabled_tasks.begin(); + + while (iterator != m_enabled_tasks.end()) { + if ((*iterator) == task_id) { return true; } + if ((*iterator) > task_id) { break; } + ++iterator; + } + + return false; +} + +int ClientTaskState::EnabledTaskCount(int task_set_id) +{ + + // Return the number of tasks in TaskSet that this character is enabled for. + + unsigned int enabled_task_index = 0; + unsigned int task_set_index = 0; + int enabled_task_count = 0; + + if ((task_set_id <= 0) || (task_set_id >= MAXTASKSETS)) { return -1; } + + while ((enabled_task_index < m_enabled_tasks.size()) && + (task_set_index < task_manager->m_task_sets[task_set_id].size())) { + + if (m_enabled_tasks[enabled_task_index] == task_manager->m_task_sets[task_set_id][task_set_index]) { + enabled_task_count++; + enabled_task_index++; + task_set_index++; + continue; + } + + if (m_enabled_tasks[enabled_task_index] < task_manager->m_task_sets[task_set_id][task_set_index]) { + enabled_task_index++; + } + else { + task_set_index++; + } + + } + + return enabled_task_count; +} + +int ClientTaskState::ActiveTasksInSet(int task_set_id) +{ + if ((task_set_id <= 0) || (task_set_id >= MAXTASKSETS)) { + return -1; + } + + int active_task_in_set_count = 0; + + for (int task_id : task_manager->m_task_sets[task_set_id]) { + if (IsTaskActive(task_id)) { + active_task_in_set_count++; + } + } + + return active_task_in_set_count; +} + +int ClientTaskState::CompletedTasksInSet(int task_set_id) +{ + if ((task_set_id <= 0) || (task_set_id >= MAXTASKSETS)) { + return -1; + } + + int completed_tasks_count = 0; + + for (int i : task_manager->m_task_sets[task_set_id]) { + if (IsTaskCompleted(i)) { + completed_tasks_count++; + } + } + + return completed_tasks_count; +} + +bool ClientTaskState::HasSlotForTask(TaskInformation *task) +{ + if (task == nullptr) { + return false; + } + + switch (task->type) { + case TaskType::Task: + return m_active_task.task_id == TASKSLOTEMPTY; + case TaskType::Shared: + return false; // todo + case TaskType::Quest: + for (auto &active_quest : m_active_quests) { + if (active_quest.task_id == TASKSLOTEMPTY) { + return true; + } + } + case TaskType::E: + return false; // removed on live + } + + return false; +} + +int ClientTaskState::GetActiveTaskID(int index) +{ + // Return the task_id from the client's specified Active Task slot. + if ((index < 0) || (index >= MAXACTIVEQUESTS)) { + return 0; + } + + return m_active_quests[index].task_id; +} + +static void DeleteCompletedTaskFromDatabase(int character_id, int task_id) +{ + LogTasks("[DeleteCompletedTasksFromDatabase] character_id [{}], task_id [{}]", character_id, task_id); + + CompletedTasksRepository::DeleteWhere( + database, + fmt::format("charid = {} and taskid = {}", character_id, task_id) + ); +} + +bool ClientTaskState::UnlockActivities(int character_id, ClientTaskInformation &task_info) +{ + bool all_activities_complete = true; + + TaskInformation *p_task_data = task_manager->m_task_data[task_info.task_id]; + if (p_task_data == nullptr) { + return true; + } + + // On loading the client state, all activities that are not completed, are + // marked as hidden. For Sequential (non-stepped) mode, we mark the first + // activity_information as active if not complete. + LogTasks( + "character_id [{}] task_id [{}] sequence_mode [{}]", + character_id, + task_info.task_id, + p_task_data->sequence_mode + ); + + if (p_task_data->sequence_mode == ActivitiesSequential) { + if (task_info.activity[0].activity_state != ActivityCompleted) { + task_info.activity[0].activity_state = ActivityActive; + } + + // Enable the next Hidden task. + for (int i = 0; i < p_task_data->activity_count; i++) { + if ((task_info.activity[i].activity_state == ActivityActive) && + (!p_task_data->activity_information[i].optional)) { + all_activities_complete = false; + break; + } + + if (task_info.activity[i].activity_state == ActivityHidden) { + task_info.activity[i].activity_state = ActivityActive; + all_activities_complete = false; + break; + } + } + + if (all_activities_complete && RuleB(TaskSystem, RecordCompletedTasks)) { + if (RuleB(TasksSystem, KeepOneRecordPerCompletedTask)) { + LogTasks("KeepOneRecord enabled"); + auto iterator = m_completed_tasks.begin(); + int erased_elements = 0; + while (iterator != m_completed_tasks.end()) { + int task_id = (*iterator).task_id; + if (task_id == task_info.task_id) { + iterator = m_completed_tasks.erase(iterator); + erased_elements++; + } + else { + ++iterator; + } + } + + LogTasks("Erased Element count is [{}]", erased_elements); + + if (erased_elements) { + m_last_completed_task_loaded -= erased_elements; + DeleteCompletedTaskFromDatabase(character_id, task_info.task_id); + } + } + + CompletedTaskInformation completed_task_information{}; + completed_task_information.task_id = task_info.task_id; + completed_task_information.completed_time = time(nullptr); + + for (int i = 0; i < p_task_data->activity_count; i++) { + completed_task_information.activity_done[i] = (task_info.activity[i].activity_state == ActivityCompleted); + } + + m_completed_tasks.push_back(completed_task_information); + } + + LogTasks("Returning sequential task, AllActivitiesComplete is [{}]", all_activities_complete); + + return all_activities_complete; + } + + // Stepped Mode + // TODO: This code is probably more complex than it needs to be + + bool current_step_complete = true; + + LogTasks( + "[UnlockActivities] Current step [{}] last_step [{}]", + task_info.current_step, + p_task_data->last_step + ); + + // If current_step is -1, this is the first call to this method since loading the + // client state. Unlock all activities with a step number of 0 + + if (task_info.current_step == -1) { + for (int i = 0; i < p_task_data->activity_count; i++) { + + if (p_task_data->activity_information[i].step_number == 0 && + task_info.activity[i].activity_state == ActivityHidden) { + task_info.activity[i].activity_state = ActivityActive; + // task_info.activity_information[i].updated=true; + } + } + task_info.current_step = 0; + } + + for (int current_step = task_info.current_step; current_step <= p_task_data->last_step; current_step++) { + for (int activity = 0; activity < p_task_data->activity_count; activity++) { + if (p_task_data->activity_information[activity].step_number == (int) task_info.current_step) { + if ((task_info.activity[activity].activity_state != ActivityCompleted) && + (!p_task_data->activity_information[activity].optional)) { + current_step_complete = false; + all_activities_complete = false; + break; + } + } + } + if (!current_step_complete) { + break; + } + task_info.current_step++; + } + + if (all_activities_complete) { + if (RuleB(TaskSystem, RecordCompletedTasks)) { + // If we are only keeping one completed record per task, and the player has done + // the same task again, erase the previous completed entry for this task. + if (RuleB(TasksSystem, KeepOneRecordPerCompletedTask)) { + LogTasksDetail("[UnlockActivities] KeepOneRecord enabled"); + auto iterator = m_completed_tasks.begin(); + int erased_elements = 0; + + while (iterator != m_completed_tasks.end()) { + int task_id = (*iterator).task_id; + if (task_id == task_info.task_id) { + iterator = m_completed_tasks.erase(iterator); + erased_elements++; + } + else { + ++iterator; + } + } + + LogTasksDetail("[UnlockActivities] Erased Element count is [{}]", erased_elements); + + if (erased_elements) { + m_last_completed_task_loaded -= erased_elements; + DeleteCompletedTaskFromDatabase(character_id, task_info.task_id); + } + } + + CompletedTaskInformation completed_task_information{}; + completed_task_information.task_id = task_info.task_id; + completed_task_information.completed_time = time(nullptr); + + for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { + completed_task_information.activity_done[activity_id] = + (task_info.activity[activity_id].activity_state == ActivityCompleted); + } + + m_completed_tasks.push_back(completed_task_information); + } + return true; + } + + // Mark all non-completed tasks in the current step as active + for (int activity = 0; activity < p_task_data->activity_count; activity++) { + if ((p_task_data->activity_information[activity].step_number == (int) task_info.current_step) && + (task_info.activity[activity].activity_state == ActivityHidden)) { + task_info.activity[activity].activity_state = ActivityActive; + task_info.activity[activity].updated = true; + } + } + + return false; +} + +void ClientTaskState::UpdateTasksOnKill(Client *client, int npc_type_id) +{ + UpdateTasksByNPC(client, ActivityKill, npc_type_id); +} + +bool ClientTaskState::UpdateTasksOnSpeakWith(Client *client, int npc_type_id) +{ + return UpdateTasksByNPC(client, ActivitySpeakWith, npc_type_id); +} + +bool ClientTaskState::UpdateTasksByNPC(Client *client, int activity_type, int npc_type_id) +{ + + int is_updating = false; + + // If the client has no tasks, there is nothing further to check. + if (!task_manager || (m_active_task_count == 0 && m_active_task.task_id == TASKSLOTEMPTY)) { // could be better ... + return false; + } + + // loop over the union of tasks and quests + for (auto &active_task : m_active_tasks) { + auto current_task = &active_task; + if (current_task->task_id == TASKSLOTEMPTY) { + continue; + } + + // Check if there are any active kill activities for this p_task_data + auto p_task_data = task_manager->m_task_data[current_task->task_id]; + if (p_task_data == nullptr) { + return false; + } + + for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { + ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; + ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; + + // We are not interested in completed or hidden activities + if (client_activity->activity_state != ActivityActive) { + continue; + } + // We are only interested in Kill activities + if (activity_info->activity_type != activity_type) { + continue; + } + // Is there a zone restriction on the activity_information ? + if (!activity_info->CheckZone(zone->GetZoneID())) { + LogTasks( + "[UPDATE] character [{}] task_id [{}] activity_id [{}] activity_type [{}] for NPC [{}] failed zone check", + client->GetName(), + current_task->task_id, + activity_id, + activity_type, + npc_type_id + ); + continue; + } + // Is the activity_information to kill this type of NPC ? + switch (activity_info->goal_method) { + case METHODSINGLEID: + if (activity_info->goal_id != npc_type_id) { + continue; + } + break; + + case METHODLIST: + if (!task_manager->m_goal_list_manager.IsInList( + activity_info->goal_id, + npc_type_id + )) { + continue; + } + break; + + default: + // If METHODQUEST, don't updated the activity_information here + continue; + } + // We found an active p_task_data to kill this type of NPC, so increment the done count + LogTasksDetail("Calling increment done count ByNPC"); + IncrementDoneCount(client, p_task_data, current_task->slot, activity_id); + is_updating = true; + } + } + + return is_updating; +} + +int ClientTaskState::ActiveSpeakTask(int npc_type_id) +{ + + // This method is to be used from Perl quests only and returns the task_id of the first + // active task found which has an active SpeakWith activity_information for this NPC. + if (!task_manager || (m_active_task_count == 0 && m_active_task.task_id == TASKSLOTEMPTY)) { // could be better ... + return 0; + } + + // loop over the union of tasks and quests + for (auto &active_task : m_active_tasks) { + auto current_task = &active_task; + if (current_task->task_id == TASKSLOTEMPTY) { + continue; + } + + TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id]; + if (p_task_data == nullptr) { + continue; + } + + for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { + ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; + ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; + + // We are not interested in completed or hidden activities + if (client_activity->activity_state != ActivityActive) { + continue; + } + if (activity_info->activity_type != ActivitySpeakWith) { + continue; + } + // Is there a zone restriction on the activity_information ? + if (!activity_info->CheckZone(zone->GetZoneID())) { + continue; + } + // Is the activity_information to speak with this type of NPC ? + if (activity_info->goal_method == METHODQUEST && activity_info->goal_id == npc_type_id) { + return current_task->task_id; + } + } + } + + return 0; +} + +int ClientTaskState::ActiveSpeakActivity(int npc_type_id, int task_id) +{ + + // This method is to be used from Perl quests only and returns the activity_id of the first + // active activity_information found in the specified task which is to SpeakWith this NPC. + if (!task_manager || (m_active_task_count == 0 && m_active_task.task_id == TASKSLOTEMPTY)) { // could be better ... + return -1; + } + if (task_id <= 0 || task_id >= MAXTASKS) { + return -1; + } + + // loop over the union of tasks and quests + for (auto &active_task : m_active_tasks) { + auto current_task = &active_task; + if (current_task->task_id != task_id) { + continue; + } + + TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id]; + if (p_task_data == nullptr) { + continue; + } + + for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { + ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; + ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; + + // We are not interested in completed or hidden activities + if (client_activity->activity_state != ActivityActive) { + continue; + } + if (activity_info->activity_type != ActivitySpeakWith) { + continue; + } + // Is there a zone restriction on the activity_information ? + if (!activity_info->CheckZone(zone->GetZoneID())) { + continue; + } + + // Is the activity_information to speak with this type of NPC ? + if (activity_info->goal_method == METHODQUEST && activity_info->goal_id == npc_type_id) { + return activity_id; + } + } + return 0; + } + return 0; +} + +void ClientTaskState::UpdateTasksForItem(Client *client, ActivityType activity_type, int item_id, int count) +{ + + // This method updates the client's task activities of the specified type which relate + // to the specified item. + // + // Type should be one of ActivityLoot, ActivityTradeSkill, ActivityFish or ActivityForage + + // If the client has no tasks, there is nothing further to check. + + LogTasks( + "[UpdateTasksForItem] activity_type [{}] item_id [{}]", + activity_type, + item_id + ); + + if (!task_manager || (m_active_task_count == 0 && m_active_task.task_id == TASKSLOTEMPTY)) { // could be better ... + return; + } + + // loop over the union of tasks and quests + for (auto &active_task : m_active_tasks) { + auto current_task = &active_task; + if (current_task->task_id == TASKSLOTEMPTY) { + continue; + } + + // Check if there are any active loot activities for this task + + TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id]; + if (p_task_data == nullptr) { + return; + } + + for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { + ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; + ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; + + // We are not interested in completed or hidden activities + if (client_activity->activity_state != ActivityActive) { + continue; + } + // We are only interested in the ActivityType we were called with + if (activity_info->activity_type != (int) activity_type) { + continue; + } + // Is there a zone restriction on the activity_information ? + if (!activity_info->CheckZone(zone->GetZoneID())) { + LogTasks( + "[UpdateTasksForItem] Error: Character [{}] activity_information type [{}] for Item [{}] failed zone check", + client->GetName(), + activity_type, + item_id + ); + continue; + } + // Is the activity_information related to this item ? + // + switch (activity_info->goal_method) { + + case METHODSINGLEID: + if (activity_info->goal_id != item_id) { continue; } + break; + + case METHODLIST: + if (!task_manager->m_goal_list_manager.IsInList( + activity_info->goal_id, + item_id + )) { continue; } + break; + + default: + // If METHODQUEST, don't updated the activity_information here + continue; + } + // We found an active task related to this item, so increment the done count + LogTasksDetail("[UpdateTasksForItem] Calling increment done count ForItem"); + IncrementDoneCount(client, p_task_data, current_task->slot, activity_id, count); + } + } +} + +void ClientTaskState::UpdateTasksOnExplore(Client *client, int explore_id) +{ + LogTasks("[UpdateTasksOnExplore] explore_id [{}]", explore_id); + if (!task_manager || (m_active_task_count == 0 && m_active_task.task_id == TASKSLOTEMPTY)) { // could be better ... + return; + } + + // loop over the union of tasks and quests + for (auto &active_task : m_active_tasks) { + auto current_task = &active_task; + if (current_task->task_id == TASKSLOTEMPTY) { + continue; + } + + // Check if there are any active explore activities for this task + + TaskInformation *task_data = task_manager->m_task_data[current_task->task_id]; + if (task_data == nullptr) { + return; + } + + for (int activity_id = 0; activity_id < task_data->activity_count; activity_id++) { + ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; + ActivityInformation *activity_info = &task_data->activity_information[activity_id]; + + // We are not interested in completed or hidden activities + if (client_activity->activity_state != ActivityActive) { + continue; + } + // We are only interested in explore activities + if (activity_info->activity_type != ActivityExplore) { + continue; + } + if (!activity_info->CheckZone(zone->GetZoneID())) { + LogTasks( + "[UpdateTasksOnExplore] character [{}] explore_id [{}] failed zone check", + client->GetName(), + explore_id + ); + continue; + } + // Is the activity_information to explore this area id ? + switch (activity_info->goal_method) { + + case METHODSINGLEID: + if (activity_info->goal_id != explore_id) { + continue; + } + break; + + case METHODLIST: + if (!task_manager->m_goal_list_manager.IsInList( + activity_info->goal_id, + explore_id + )) { + continue; + } + break; + + default: + // If METHODQUEST, don't updated the activity_information here + continue; + } + + // We found an active task to explore this area, so set done count to goal count + // (Only a goal count of 1 makes sense for explore activities?) + LogTasks( + "[UpdateTasksOnExplore] character [{}] explore_id [{}] increment on explore", + client->GetName(), + explore_id + ); + + IncrementDoneCount( + client, + task_data, + current_task->slot, + activity_id, + activity_info->goal_count - current_task->activity[activity_id].done_count + ); + } + } +} + +bool ClientTaskState::UpdateTasksOnDeliver( + Client *client, + std::list &items, + int cash, + int npc_type_id +) +{ + bool is_updated = false; + + LogTasks("[UpdateTasksOnDeliver] [{}]", npc_type_id); + if (!task_manager || (m_active_task_count == 0 && m_active_task.task_id == TASKSLOTEMPTY)) { // could be better ... + return false; + } + + // loop over the union of tasks and quests + for (int i = 0; i < MAXACTIVEQUESTS + 1; i++) { + auto current_task = &m_active_tasks[i]; + if (current_task->task_id == TASKSLOTEMPTY) { + continue; + } + + // Check if there are any active deliver activities for this task + TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id]; + if (p_task_data == nullptr) { + return false; + } + + for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { + ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; + ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; + + // We are not interested in completed or hidden activities + if (client_activity->activity_state != ActivityActive) { + continue; + } + + // We are only interested in Deliver activities + if (activity_info->activity_type != ActivityDeliver && + activity_info->activity_type != ActivityGiveCash) { + continue; + } + // Is there a zone restriction on the activity_information ? + if (!activity_info->CheckZone(zone->GetZoneID())) { + Log( + Logs::General, Logs::Tasks, + "[UPDATE] Char: %s Deliver activity_information failed zone check (current zone %i, need zone " + "%s", + client->GetName(), zone->GetZoneID(), activity_info->zones.c_str()); + continue; + } + // Is the activity_information to deliver to this NPCTypeID ? + if (activity_info->deliver_to_npc != npc_type_id) { + continue; + } + // Is the activity_information related to these items ? + // + if ((activity_info->activity_type == ActivityGiveCash) && cash) { + LogTasks("[UpdateTasksOnDeliver] Increment on GiveCash"); + IncrementDoneCount(client, p_task_data, i, activity_id, cash); + is_updated = true; + } + else { + for (auto &item : items) { + switch (activity_info->goal_method) { + case METHODSINGLEID: + if (activity_info->goal_id != item->GetID()) { + continue; + } + break; + + case METHODLIST: + if (!task_manager->m_goal_list_manager.IsInList( + activity_info->goal_id, + item->GetID())) { + continue; + } + break; + + default: + // If METHODQUEST, don't updated the activity_information here + continue; + } + // We found an active task related to this item, so increment the done count + LogTasks("[UpdateTasksOnDeliver] Increment on GiveItem"); + IncrementDoneCount( + client, + p_task_data, + current_task->slot, + activity_id, + item->GetCharges() <= 0 ? 1 : item->GetCharges() + ); + is_updated = true; + } + } + } + } + + return is_updated; +} + +void ClientTaskState::UpdateTasksOnTouch(Client *client, int zone_id) +{ + // If the client has no tasks, there is nothing further to check. + + LogTasks("[UpdateTasksOnTouch] [{}] ", zone_id); + if (!task_manager || (m_active_task_count == 0 && m_active_task.task_id == TASKSLOTEMPTY)) { // could be better ... + return; + } + + // loop over the union of tasks and quests + for (auto &active_task : m_active_tasks) { + auto current_task = &active_task; + if (current_task->task_id == TASKSLOTEMPTY) { + continue; + } + + // Check if there are any active explore activities for this task + TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id]; + if (p_task_data == nullptr) { + return; + } + + for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) { + ClientActivityInformation *client_activity = ¤t_task->activity[activity_id]; + ActivityInformation *activity_info = &p_task_data->activity_information[activity_id]; + + // We are not interested in completed or hidden activities + if (current_task->activity[activity_id].activity_state != ActivityActive) { + continue; + } + // We are only interested in touch activities + if (activity_info->activity_type != ActivityTouch) { + continue; + } + if (activity_info->goal_method != METHODSINGLEID) { + continue; + } + if (!activity_info->CheckZone(zone_id)) { + LogTasks( + "[UpdateTasksOnTouch] character [{}] Touch activity_information failed zone check", + client->GetName() + ); + continue; + } + + // We found an active task to zone into this zone, so set done count to goal count + // (Only a goal count of 1 makes sense for touch activities?) + LogTasks("[UpdateTasksOnTouch] Increment on Touch"); + IncrementDoneCount( + client, + p_task_data, + current_task->slot, + activity_id, + activity_info->goal_count - current_task->activity[activity_id].done_count + ); + } + } +} + +void ClientTaskState::IncrementDoneCount( + Client *client, + TaskInformation *task_information, + int task_index, + int activity_id, + int count, + bool ignore_quest_update +) +{ + Log(Logs::General, Logs::Tasks, "[UPDATE] IncrementDoneCount"); + + auto info = GetClientTaskInfo(task_information->type, task_index); + if (info == nullptr) { + return; + } + + info->activity[activity_id].done_count += count; + + if (info->activity[activity_id].done_count > task_information->activity_information[activity_id].goal_count) { + info->activity[activity_id].done_count = task_information->activity_information[activity_id].goal_count; + } + + if (!ignore_quest_update) { + char buf[24]; + snprintf( + buf, + 23, + "%d %d %d", + info->activity[activity_id].done_count, + info->activity[activity_id].activity_id, + info->task_id + ); + buf[23] = '\0'; + parse->EventPlayer(EVENT_TASK_UPDATE, client, buf, 0); + } + + info->activity[activity_id].updated = true; + // Have we reached the goal count for this activity_information ? + if (info->activity[activity_id].done_count >= task_information->activity_information[activity_id].goal_count) { + Log( + Logs::General, Logs::Tasks, "[UPDATE] Done (%i) = Goal (%i) for activity_information %i", + info->activity[activity_id].done_count, + task_information->activity_information[activity_id].goal_count, + activity_id + ); + + // Flag the activity_information as complete + info->activity[activity_id].activity_state = ActivityCompleted; + // Unlock subsequent activities for this task + bool task_complete = UnlockActivities(client->CharacterID(), *info); + Log(Logs::General, Logs::Tasks, "[UPDATE] TaskCompleted is %i", task_complete); + // and by the 'Task Stage Completed' message + client->SendTaskActivityComplete(info->task_id, activity_id, task_index, task_information->type); + // Send the updated task/activity_information list to the client + task_manager->SendSingleActiveTaskToClient(client, *info, task_complete, false); + // Inform the client the task has been updated, both by a chat message + client->Message(Chat::White, "Your task '%s' has been updated.", task_information->title.c_str()); + + if (task_information->activity_information[activity_id].goal_method != METHODQUEST) { + if (!ignore_quest_update) { + char buf[24]; + snprintf(buf, 23, "%d %d", info->task_id, info->activity[activity_id].activity_id); + buf[23] = '\0'; + parse->EventPlayer(EVENT_TASK_STAGE_COMPLETE, client, buf, 0); + } + /* QS: PlayerLogTaskUpdates :: Update */ + if (RuleB(QueryServ, PlayerLogTaskUpdates)) { + std::string event_desc = StringFormat( + "Task Stage Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", + info->task_id, + info->activity[activity_id].activity_id, + info->activity[activity_id].done_count, + client->GetZoneID(), + client->GetInstanceID()); + QServ->PlayerLogEvent(Player_Log_Task_Updates, client->CharacterID(), event_desc); + } + } + + // If this task is now complete, the Completed tasks will have been + // updated in UnlockActivities. Send the completed task list to the + // client. This is the same sequence the packets are sent on live. + if (task_complete) { + char buf[24]; + snprintf( + buf, + 23, + "%d %d %d", + info->activity[activity_id].done_count, + info->activity[activity_id].activity_id, + info->task_id + ); + buf[23] = '\0'; + parse->EventPlayer(EVENT_TASK_COMPLETE, client, buf, 0); + + /* QS: PlayerLogTaskUpdates :: Complete */ + if (RuleB(QueryServ, PlayerLogTaskUpdates)) { + std::string event_desc = StringFormat( + "Task Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", + info->task_id, + info->activity[activity_id].activity_id, + info->activity[activity_id].done_count, + client->GetZoneID(), + client->GetInstanceID()); + QServ->PlayerLogEvent(Player_Log_Task_Updates, client->CharacterID(), event_desc); + } + + task_manager->SendCompletedTasksToClient(client, this); + client->SendTaskActivityComplete(info->task_id, 0, task_index, task_information->type, 0); + task_manager->SaveClientState(client, this); + //c->SendTaskComplete(TaskIndex); + client->CancelTask(task_index, task_information->type); + //if(Task->reward_method != METHODQUEST) RewardTask(c, Task); + // If Experience and/or cash rewards are set, reward them from the task even if reward_method is METHODQUEST + RewardTask(client, task_information); + //RemoveTask(c, TaskIndex); + + } + + } + else { + // Send an updated packet for this single activity_information + task_manager->SendTaskActivityLong( + client, + info->task_id, + activity_id, + task_index, + task_information->activity_information[activity_id].optional + ); + task_manager->SaveClientState(client, this); + } +} + +void ClientTaskState::RewardTask(Client *client, TaskInformation *task_information) +{ + + if (!task_information || !client) { + return; + } + + const EQ::ItemData *item_data; + std::vector reward_list; + + switch (task_information->reward_method) { + case METHODSINGLEID: { + if (task_information->reward_id) { + client->SummonItem(task_information->reward_id); + item_data = database.GetItem(task_information->reward_id); + if (item_data) { + client->Message(Chat::Yellow, "You receive %s as a reward.", item_data->Name); + } + } + break; + } + case METHODLIST: { + reward_list = task_manager->m_goal_list_manager.GetListContents(task_information->reward_id); + for (int item_id : reward_list) { + client->SummonItem(item_id); + item_data = database.GetItem(item_id); + if (item_data) { + client->Message(Chat::Yellow, "You receive %s as a reward.", item_data->Name); + } + } + break; + } + default: { + // Nothing special done for METHODQUEST + break; + } + } + + if (!task_information->completion_emote.empty()) { + client->SendColoredText( + Chat::Yellow, + task_information->completion_emote + ); + } // unsure if they use this packet or color, should work + + // just use normal NPC faction ID stuff + if (task_information->faction_reward) { + client->SetFactionLevel( + client->CharacterID(), + task_information->faction_reward, + client->GetBaseClass(), + client->GetBaseRace(), + client->GetDeity() + ); + } + + if (task_information->cash_reward) { + int platinum, gold, silver, copper; + + copper = task_information->cash_reward; + client->AddMoneyToPP(copper, true); + + platinum = copper / 1000; + copper = copper - (platinum * 1000); + gold = copper / 100; + copper = copper - (gold * 100); + silver = copper / 10; + copper = copper - (silver * 10); + + std::string cash_message; + + if (platinum > 0) { + cash_message = "You receive "; + cash_message += itoa(platinum); + cash_message += " platinum"; + } + if (gold > 0) { + if (cash_message.length() == 0) { + cash_message = "You receive "; + } + else { + cash_message += ","; + } + cash_message += itoa(gold); + cash_message += " gold"; + } + if (silver > 0) { + if (cash_message.length() == 0) { + cash_message = "You receive "; + } + else { + cash_message += ","; + } + cash_message += itoa(silver); + cash_message += " silver"; + } + if (copper > 0) { + if (cash_message.length() == 0) { + cash_message = "You receive "; + } + else { + cash_message += ","; + } + cash_message += itoa(copper); + cash_message += " copper"; + } + cash_message += " pieces."; + client->Message(Chat::Yellow, cash_message.c_str()); + } + int32 experience_reward = task_information->experience_reward; + if (experience_reward > 0) { + client->AddEXP(experience_reward); + } + if (experience_reward < 0) { + uint32 pos_reward = experience_reward * -1; + // Minimal Level Based Exp reward Setting is 101 (1% exp at level 1) + if (pos_reward > 100 && pos_reward < 25700) { + uint8 max_level = pos_reward / 100; + uint8 exp_percent = pos_reward - (max_level * 100); + client->AddLevelBasedExp(exp_percent, max_level); + } + } + + client->SendSound(); +} + +bool ClientTaskState::IsTaskActive(int task_id) +{ + if (m_active_task.task_id == task_id) { + return true; + } + + if (m_active_task_count == 0 || task_id == 0) { + return false; + } + + for (auto &active_quest : m_active_quests) { + if (active_quest.task_id == task_id) { + return true; + } + } + + return false; +} + +void ClientTaskState::FailTask(Client *client, int task_id) +{ + LogTasks( + "[FailTask] Failing task for character [{}] task_id [{}] task_count [{}]", + client->GetCleanName(), + task_id, + m_active_task_count + ); + + if (m_active_task.task_id == task_id) { + client->SendTaskFailed(task_id, 0, TaskType::Task); + // Remove the task from the client + client->CancelTask(0, TaskType::Task); + return; + } + + // TODO: shared tasks + + if (m_active_task_count == 0) { + return; + } + + for (int i = 0; i < MAXACTIVEQUESTS; i++) { + if (m_active_quests[i].task_id == task_id) { + client->SendTaskFailed(m_active_quests[i].task_id, i, TaskType::Quest); + // Remove the task from the client + client->CancelTask(i, TaskType::Quest); + return; + } + } +} + +// TODO: Shared tasks +bool ClientTaskState::IsTaskActivityActive(int task_id, int activity_id) +{ + LogTasks("[IsTaskActivityActive] task_id [{}] activity_id [{}]", task_id, activity_id); + + // Quick sanity check + if (activity_id < 0) { + return false; + } + if (m_active_task_count == 0 && m_active_task.task_id == TASKSLOTEMPTY) { + return false; + } + + int active_task_index = -1; + auto task_type = TaskType::Task; + + if (m_active_task.task_id == task_id) { + active_task_index = 0; + } + + if (active_task_index == -1) { + for (int i = 0; i < MAXACTIVEQUESTS; i++) { + if (m_active_quests[i].task_id == task_id) { + active_task_index = i; + task_type = TaskType::Quest; + break; + } + } + } + + // The client does not have this task + if (active_task_index == -1) { + return false; + } + + auto info = GetClientTaskInfo(task_type, active_task_index); + + if (info == nullptr) { + return false; + } + + TaskInformation *p_task_data = task_manager->m_task_data[info->task_id]; + + // The task is invalid + if (p_task_data == nullptr) { + return false; + } + + // The activity_id is out of range + if (activity_id >= p_task_data->activity_count) { + return false; + } + + LogTasks( + "[IsTaskActivityActive] (Update) task_id [{}] activity_id [{}] activity_state [{}]", + task_id, + activity_id, + info->activity[activity_id].activity_state + ); + + return (info->activity[activity_id].activity_state == ActivityActive); +} + +void ClientTaskState::UpdateTaskActivity( + Client *client, + int task_id, + int activity_id, + int count, + bool ignore_quest_update /*= false*/) +{ + LogTasks( + "[UpdateTaskActivity] Increment done count (pre) on UpdateTaskActivity task_id [{}] activity_id [{}] count [{}]", + task_id, + activity_id, + count + ); + + // Quick sanity check + if (activity_id < 0 || (m_active_task_count == 0 && m_active_task.task_id == TASKSLOTEMPTY)) { + return; + } + + int active_task_index = -1; + auto type = TaskType::Task; + + if (m_active_task.task_id == task_id) { + active_task_index = 0; + } + + if (active_task_index == -1) { + for (int i = 0; i < MAXACTIVEQUESTS; i++) { + if (m_active_quests[i].task_id == task_id) { + active_task_index = i; + type = TaskType::Quest; + break; + } + } + } + + // The client does not have this task + if (active_task_index == -1) { + return; + } + + auto info = GetClientTaskInfo(type, active_task_index); + if (info == nullptr) { + return; + } + + TaskInformation *p_task_data = task_manager->m_task_data[info->task_id]; + + // The task is invalid + if (p_task_data == nullptr) { + return; + } + + // The activity_id is out of range + if (activity_id >= p_task_data->activity_count) { + return; + } + + // The activity_information is not currently active + if (info->activity[activity_id].activity_state == ActivityHidden) { + return; + } + + LogTasks( + "[UpdateTaskActivity] Increment done count (done) on UpdateTaskActivity task_id [{}] activity_id [{}] count [{}]", + task_id, + activity_id, + count + ); + + IncrementDoneCount(client, p_task_data, active_task_index, activity_id, count, ignore_quest_update); +} + +void ClientTaskState::ResetTaskActivity(Client *client, int task_id, int activity_id) +{ + LogTasks( + "[ResetTaskActivity] (pre) client [{}] task_id [{}] activity_id [{}]", + client->GetCleanName(), + task_id, + activity_id + ); + + // Quick sanity check + if (activity_id < 0 || (m_active_task_count == 0 && m_active_task.task_id == TASKSLOTEMPTY)) { + return; + } + + int active_task_index = -1; + auto type = TaskType::Task; + if (m_active_task.task_id == task_id) { + active_task_index = 0; + } + + if (active_task_index == -1) { + for (int i = 0; i < MAXACTIVEQUESTS; i++) { + if (m_active_quests[i].task_id == task_id) { + active_task_index = i; + type = TaskType::Quest; + break; + } + } + } + + // The client does not have this task + if (active_task_index == -1) { + return; + } + + auto info = GetClientTaskInfo(type, active_task_index); + if (info == nullptr) { + return; + } + + TaskInformation *p_task_data = task_manager->m_task_data[info->task_id]; + if (p_task_data == nullptr) { + return; + } + + // The activity_id is out of range + if (activity_id >= p_task_data->activity_count) { + return; + } + + // The activity_information is not currently active + if (info->activity[activity_id].activity_state == ActivityHidden) { + return; + } + + LogTasks( + "[ResetTaskActivity] (IncrementDoneCount) client [{}] task_id [{}] activity_id [{}]", + client->GetCleanName(), + task_id, + activity_id + ); + + IncrementDoneCount( + client, + p_task_data, + active_task_index, + activity_id, + (info->activity[activity_id].done_count * -1), + false + ); +} + +void ClientTaskState::ShowClientTasks(Client *client) +{ + client->Message(Chat::White, "------------------------------------------------"); + client->Message(Chat::White, "# Task Information | Client [%s]", client->GetCleanName()); +// client->Message(Chat::White, "------------------------------------------------"); + if (m_active_task.task_id != TASKSLOTEMPTY) { + client->Message( + Chat::White, + "Task: %i %s", + m_active_task.task_id, + task_manager->m_task_data[m_active_task.task_id]->title.c_str() + ); + client->Message( + Chat::White, + " description: [%s]\n", + task_manager->m_task_data[m_active_task.task_id]->description.c_str() + ); + for (int activity_id = 0; activity_id < task_manager->GetActivityCount(m_active_task.task_id); activity_id++) { + client->Message( + Chat::White, + " activity_information: %2d, done_count: %2d, Status: %d (0=Hidden, 1=Active, 2=Complete)", + m_active_task.activity[activity_id].activity_id, + m_active_task.activity[activity_id].done_count, + m_active_task.activity[activity_id].activity_state + ); + } + } + + for (auto &active_quest : m_active_quests) { + if (active_quest.task_id == TASKSLOTEMPTY) { + continue; + } + + client->Message(Chat::White, "------------------------------------------------"); + client->Message( + Chat::White, "# Quest | task_id [%i] title [%s]", + active_quest.task_id, + task_manager->m_task_data[active_quest.task_id]->title.c_str() + ); + client->Message(Chat::White, "------------------------------------------------"); + + client->Message( + Chat::White, + " -- Description [%s]\n", + task_manager->m_task_data[active_quest.task_id]->description.c_str() + ); + + for (int activity_id = 0; activity_id < task_manager->GetActivityCount(active_quest.task_id); activity_id++) { + std::vector update_increments = {"1", "5", "50"}; + std::string update_saylinks; + + for (auto &increment: update_increments) { + auto task_update_saylink = EQ::SayLinkEngine::GenerateQuestSaylink( + fmt::format( + "#task update {} {} {}", + active_quest.task_id, + active_quest.activity[activity_id].activity_id, + increment + ), + false, + increment + ); + + update_saylinks += "[" + task_update_saylink + "] "; + } + + client->Message( + Chat::White, + " --- activity_id [%i] done_count [%i] state [%d] (0=hidden 1=active 2=complete) | Update %s", + active_quest.activity[activity_id].activity_id, + active_quest.activity[activity_id].done_count, + active_quest.activity[activity_id].activity_state, + update_saylinks.c_str() + ); + } + } + + client->Message(Chat::White, "------------------------------------------------"); +} + +// TODO: Shared Task +int ClientTaskState::TaskTimeLeft(int task_id) +{ + if (m_active_task.task_id == task_id) { + int time_now = time(nullptr); + + TaskInformation *p_task_data = task_manager->m_task_data[task_id]; + if (p_task_data == nullptr) { + return -1; + } + + if (!p_task_data->duration) { + return -1; + } + + int time_left = (m_active_task.accepted_time + p_task_data->duration - time_now); + + return (time_left > 0 ? time_left : 0); + } + + if (m_active_task_count == 0) { + return -1; + } + + for (auto &active_quest : m_active_quests) { + if (active_quest.task_id != task_id) { + continue; + } + + int time_now = time(nullptr); + + TaskInformation *p_task_data = task_manager->m_task_data[active_quest.task_id]; + if (p_task_data == nullptr) { + return -1; + } + + if (!p_task_data->duration) { + return -1; + } + + int time_left = (active_quest.accepted_time + p_task_data->duration - time_now); + + // If Timeleft is negative, return 0, else return the number of seconds left + + return (time_left > 0 ? time_left : 0); + } + + return -1; +} + +int ClientTaskState::IsTaskCompleted(int task_id) +{ + + // Returns: -1 if RecordCompletedTasks is not true + // +1 if the task has been completed + // 0 if the task has not been completed + + if (!(RuleB(TaskSystem, RecordCompletedTasks))) { + return -1; + } + + for (auto &completed_task : m_completed_tasks) { + LogTasks("[IsTaskCompleted] Comparing compelted task [{}] with [{}]", completed_task.task_id, task_id); + if (completed_task.task_id == task_id) { + return 1; + } + } + + return 0; +} + +bool ClientTaskState::TaskOutOfTime(TaskType task_type, int index) +{ + // Returns true if the Task in the specified slot has a time limit that has been exceeded. + auto info = GetClientTaskInfo(task_type, index); + if (info == nullptr) { + return false; + } + + // make sure the task_id is at least maybe in our array + if (info->task_id <= 0 || info->task_id >= MAXTASKS) { + return false; + } + + int time_now = time(nullptr); + TaskInformation *task_data = task_manager->m_task_data[info->task_id]; + if (task_data == nullptr) { + return false; + } + + return (task_data->duration && (info->accepted_time + task_data->duration <= time_now)); +} + +void ClientTaskState::TaskPeriodicChecks(Client *client) +{ + if (m_active_task.task_id != TASKSLOTEMPTY) { + if (TaskOutOfTime(TaskType::Task, 0)) { + // Send Red Task Failed Message + client->SendTaskFailed(m_active_task.task_id, 0, TaskType::Task); + // Remove the task from the client + client->CancelTask(0, TaskType::Task); + // It is a conscious decision to only fail one task per call to this method, + // otherwise the player will not see all the failed messages where multiple + // tasks fail at the same time. + return; + } + } + + // TODO: shared tasks -- although that will probably be manager in world checking and telling zones to fail us + + if (m_active_task_count == 0) { + return; + } + + // Check for tasks that have failed because they have not been completed in the specified time + // + for (int task_index = 0; task_index < MAXACTIVEQUESTS; task_index++) { + if (m_active_quests[task_index].task_id == TASKSLOTEMPTY) { + continue; + } + + if (TaskOutOfTime(TaskType::Quest, task_index)) { + // Send Red Task Failed Message + client->SendTaskFailed(m_active_quests[task_index].task_id, task_index, TaskType::Quest); + // Remove the task from the client + client->CancelTask(task_index, TaskType::Quest); + // It is a conscious decision to only fail one task per call to this method, + // otherwise the player will not see all the failed messages where multiple + // tasks fail at the same time. + break; + } + } + + // Check for activities that require zoning into a specific zone. + // This is done in this method because it gives an extra few seconds for the client screen to display + // the zone before we send the 'Task activity_information Completed' message. + // + if (!m_checked_touch_activities) { + UpdateTasksOnTouch(client, zone->GetZoneID()); + m_checked_touch_activities = true; + } +} + +bool ClientTaskState::IsTaskActivityCompleted(TaskType task_type, int index, int activity_id) +{ + switch (task_type) { + case TaskType::Task: + if (index != 0) { + return false; + } + return m_active_task.activity[activity_id].activity_state == ActivityCompleted; + case TaskType::Shared: + return false; // TODO: shared tasks + case TaskType::Quest: + if (index < MAXACTIVEQUESTS) { + return m_active_quests[index].activity[activity_id].activity_state == ActivityCompleted; + } + default: + return false; + } + +} + +// should we be defaulting to hidden? +ActivityState ClientTaskState::GetTaskActivityState(TaskType task_type, int index, int activity_id) +{ + switch (task_type) { + case TaskType::Task: + if (index != 0) { + return ActivityHidden; + } + return m_active_task.activity[activity_id].activity_state; + case TaskType::Shared: + return ActivityHidden; // TODO: shared tasks + case TaskType::Quest: + if (index < MAXACTIVEQUESTS) { + return m_active_quests[index].activity[activity_id].activity_state; + } + default: + return ActivityHidden; + } +} + +int ClientTaskState::GetTaskActivityDoneCount(TaskType task_type, int index, int activity_id) +{ + switch (task_type) { + case TaskType::Task: + if (index != 0) { + return 0; + } + return m_active_task.activity[activity_id].done_count; + case TaskType::Shared: + return 0; // TODO: shared tasks + case TaskType::Quest: + if (index < MAXACTIVEQUESTS) { + return m_active_quests[index].activity[activity_id].done_count; + } + default: + return 0; + } +} + +int ClientTaskState::GetTaskActivityDoneCountFromTaskID(int task_id, int activity_id) +{ + if (m_active_task.task_id == task_id) { + return m_active_task.activity[activity_id].done_count; + } + + // TODO: shared tasks + + int active_task_index = -1; + + for (int task_index = 0; task_index < MAXACTIVEQUESTS; task_index++) { + if (m_active_quests[task_index].task_id == task_id) { + active_task_index = task_index; + break; + } + } + + if (active_task_index == -1) { + return 0; + } + + if (m_active_quests[active_task_index].activity[activity_id].done_count) { + return m_active_quests[active_task_index].activity[activity_id].done_count; + } + else { + return 0; + } +} + +int ClientTaskState::GetTaskStartTime(TaskType task_type, int index) +{ + switch (task_type) { + case TaskType::Task: + return m_active_task.accepted_time; + case TaskType::Quest: + return m_active_quests[index].accepted_time; + case TaskType::Shared: // TODO + default: + return -1; + } +} + +void ClientTaskState::CancelAllTasks(Client *client) +{ + + // This method exists solely to be called during #task reloadall + // It removes tasks from the in-game client state ready for them to be + // resent to the client, in case an updated task fails to load + + CancelTask(client, 0, TaskType::Task, false); + m_active_task.task_id = TASKSLOTEMPTY; + + for (int task_index = 0; task_index < MAXACTIVEQUESTS; task_index++) + if (m_active_quests[task_index].task_id != TASKSLOTEMPTY) { + CancelTask(client, task_index, TaskType::Quest, false); + m_active_quests[task_index].task_id = TASKSLOTEMPTY; + } + + // TODO: shared +} + +void ClientTaskState::CancelTask(Client *client, int sequence_number, TaskType task_type, bool remove_from_db) +{ + auto outapp = new EQApplicationPacket(OP_CancelTask, sizeof(CancelTask_Struct)); + + CancelTask_Struct *cts = (CancelTask_Struct *) outapp->pBuffer; + cts->SequenceNumber = sequence_number; + cts->type = static_cast(task_type); + + Log(Logs::General, Logs::Tasks, "[UPDATE] CancelTask"); + + client->QueuePacket(outapp); + safe_delete(outapp); + + if (remove_from_db) { + RemoveTask(client, sequence_number, task_type); + } +} + +void ClientTaskState::RemoveTask(Client *client, int sequence_number, TaskType task_type) +{ + int character_id = client->CharacterID(); + Log(Logs::General, Logs::Tasks, "[UPDATE] ClientTaskState Cancel Task %i ", sequence_number); + + int task_id = -1; + switch (task_type) { + case TaskType::Task: + if (sequence_number == 0) { + task_id = m_active_task.task_id; + } + break; + case TaskType::Quest: + if (sequence_number < MAXACTIVEQUESTS) { + task_id = m_active_quests[sequence_number].task_id; + } + break; + case TaskType::Shared: // TODO: + default: + break; + } + + CharacterActivitiesRepository::DeleteWhere( + database, + fmt::format("charid = {} AND taskid = {}", character_id, task_id) + ); + + CharacterTasksRepository::DeleteWhere( + database, + fmt::format("charid = {} AND taskid = {} AND type = {}", character_id, task_id, static_cast(task_type)) + ); + + switch (task_type) { + case TaskType::Task: + m_active_task.task_id = TASKSLOTEMPTY; + break; + case TaskType::Shared: + break; // TODO: shared tasks + case TaskType::Quest: + m_active_quests[sequence_number].task_id = TASKSLOTEMPTY; + m_active_task_count--; + break; + default: + break; + } +} + +void ClientTaskState::RemoveTaskByTaskID(Client *client, uint32 task_id) +{ + auto task_type = task_manager->GetTaskType(task_id); + int character_id = client->CharacterID(); + + CharacterActivitiesRepository::DeleteWhere( + database, + fmt::format("charid = {} AND taskid = {}", character_id, task_id) + ); + + CharacterTasksRepository::DeleteWhere( + database, + fmt::format("charid = {} AND taskid = {} AND type = {}", character_id, task_id, (int) task_type) + ); + + switch (task_type) { + case TaskType::Task: { + if (m_active_task.task_id == task_id) { + auto outapp = new EQApplicationPacket(OP_CancelTask, sizeof(CancelTask_Struct)); + CancelTask_Struct *cts = (CancelTask_Struct *) outapp->pBuffer; + cts->SequenceNumber = 0; + cts->type = static_cast(task_type); + LogTasks("[UPDATE] RemoveTaskByTaskID found Task [{}]", task_id); + client->QueuePacket(outapp); + safe_delete(outapp); + m_active_task.task_id = TASKSLOTEMPTY; + } + break; + } + case TaskType::Shared: { + break; // TODO: shared tasks + } + case TaskType::Quest: { + for (int active_quest = 0; active_quest < MAXACTIVEQUESTS; active_quest++) { + if (m_active_quests[active_quest].task_id == task_id) { + auto outapp = new EQApplicationPacket(OP_CancelTask, sizeof(CancelTask_Struct)); + CancelTask_Struct *cts = (CancelTask_Struct *) outapp->pBuffer; + cts->SequenceNumber = active_quest; + cts->type = static_cast(task_type); + LogTasks("[UPDATE] RemoveTaskByTaskID found Quest [{}] at index [{}]", task_id, active_quest); + m_active_quests[active_quest].task_id = TASKSLOTEMPTY; + m_active_task_count--; + client->QueuePacket(outapp); + safe_delete(outapp); + } + } + } + default: { + break; + } + } +} + +void ClientTaskState::AcceptNewTask(Client *client, int task_id, int npc_type_id, bool enforce_level_requirement) +{ + if (!task_manager || task_id < 0 || task_id >= MAXTASKS) { + client->Message(Chat::Red, "Task system not functioning, or task_id %i out of range.", task_id); + return; + } + + auto task = task_manager->m_task_data[task_id]; + + if (task == nullptr) { + client->Message(Chat::Red, "Invalid task_id %i", task_id); + return; + } + + bool max_tasks = false; + + switch (task->type) { + case TaskType::Task: + if (m_active_task.task_id != TASKSLOTEMPTY) { + max_tasks = true; + } + break; + case TaskType::Shared: // TODO: shared tasks + // if (something) + max_tasks = true; + break; + case TaskType::Quest: + if (m_active_task_count == MAXACTIVEQUESTS) { + max_tasks = true; + } + break; + default: + break; + } + + if (max_tasks) { + client->Message( + Chat::Red, + "You already have the maximum allowable number of active tasks (%i)", + MAXACTIVEQUESTS + ); + return; + } + + // only Quests can have more than one, so don't need to check others + if (task->type == TaskType::Quest) { + for (auto &active_quest : m_active_quests) { + if (active_quest.task_id == task_id) { + client->Message(Chat::Red, "You have already been assigned this task."); + return; + } + } + } + + if (enforce_level_requirement && !task_manager->ValidateLevel(task_id, client->GetLevel())) { + client->Message(Chat::Red, "You are outside the level range of this task."); + return; + } + + if (!task_manager->IsTaskRepeatable(task_id) && IsTaskCompleted(task_id)) { + return; + } + + // We do it this way, because when the Client cancels a task, it retains the sequence number of the remaining + // tasks in it's window, until something causes the TaskDescription packets to be sent again. We could just + // resend all the active task data to the client when it cancels a task, but that could be construed as a + // waste of bandwidth. + // + ClientTaskInformation *active_slot = nullptr; + switch (task->type) { + case TaskType::Task: + active_slot = &m_active_task; + break; + case TaskType::Shared: // TODO: shared + active_slot = nullptr; + break; + case TaskType::Quest: + for (int task_index = 0; task_index < MAXACTIVEQUESTS; task_index++) { + Log(Logs::General, Logs::Tasks, + "[UPDATE] ClientTaskState Looking for free slot in slot %i, found task_id of %i", task_index, + m_active_quests[task_index].task_id); + if (m_active_quests[task_index].task_id == 0) { + active_slot = &m_active_quests[task_index]; + break; + } + } + break; + default: + break; + } + + // This shouldn't happen unless there is a bug in the handling of ActiveTaskCount somewhere + if (active_slot == nullptr) { + client->Message( + Chat::Red, + "You already have the maximum allowable number of active tasks (%i)", + MAXACTIVEQUESTS + ); + return; + } + + active_slot->task_id = task_id; + active_slot->accepted_time = time(nullptr); + active_slot->updated = true; + active_slot->current_step = -1; + + for (int activity_id = 0; activity_id < task_manager->m_task_data[task_id]->activity_count; activity_id++) { + active_slot->activity[activity_id].activity_id = activity_id; + active_slot->activity[activity_id].done_count = 0; + active_slot->activity[activity_id].activity_state = ActivityHidden; + active_slot->activity[activity_id].updated = true; + } + + UnlockActivities(client->CharacterID(), *active_slot); + + if (task->type == TaskType::Quest) { + m_active_task_count++; + } + + task_manager->SendSingleActiveTaskToClient(client, *active_slot, false, true); + client->Message( + Chat::White, + "You have been assigned the task '%s'.", + task_manager->m_task_data[task_id]->title.c_str() + ); + task_manager->SaveClientState(client, this); + std::string buf = std::to_string(task_id); + + NPC *npc = entity_list.GetID(npc_type_id)->CastToNPC(); + if (npc) { + parse->EventNPC(EVENT_TASK_ACCEPTED, npc, client, buf.c_str(), 0); + } +} + +void ClientTaskState::ProcessTaskProximities(Client *client, float x, float y, float z) +{ + float last_x = client->ProximityX(); + float last_y = client->ProximityY(); + float last_z = client->ProximityZ(); + + if ((last_x == x) && (last_y == y) && (last_z == z)) { + return; + } + + LogTasksDetail("[ProcessTaskProximities] Checking proximities for Position x[{}] y[{}] z[{}]", x, y, z); + int explore_id = task_manager->m_proximity_manager.CheckProximities(x, y, z); + if (explore_id > 0) { + LogTasksDetail( + "[ProcessTaskProximities] Position x[{}] y[{}] z[{}] is within proximity explore_id [{}]", + x, + y, + z, + explore_id + ); + + UpdateTasksOnExplore(client, explore_id); + } +} diff --git a/zone/task_client_state.h b/zone/task_client_state.h new file mode 100644 index 000000000..6812e99c6 --- /dev/null +++ b/zone/task_client_state.h @@ -0,0 +1,111 @@ +#ifndef EQEMU_TASK_CLIENT_STATE_H +#define EQEMU_TASK_CLIENT_STATE_H + +#include "tasks.h" +#include "../common/types.h" +#include +#include +#include +#include + +class ClientTaskState { + +public: + ClientTaskState(); + ~ClientTaskState(); + void ShowClientTasks(Client *client); + inline int GetActiveTaskCount() { return m_active_task_count; } + int GetActiveTaskID(int index); + bool IsTaskActivityCompleted(TaskType task_type, int index, int activity_id); + int GetTaskActivityDoneCount(TaskType task_type, int index, int activity_id); + int GetTaskActivityDoneCountFromTaskID(int task_id, int activity_id); + int GetTaskStartTime(TaskType task_type, int index); + void AcceptNewTask(Client *client, int task_id, int npc_type_id, bool enforce_level_requirement = false); + void FailTask(Client *client, int task_id); + int TaskTimeLeft(int task_id); + int IsTaskCompleted(int task_id); + bool IsTaskActive(int task_id); + bool IsTaskActivityActive(int task_id, int activity_id); + ActivityState GetTaskActivityState(TaskType task_type, int index, int activity_id); + void UpdateTaskActivity(Client *client, int task_id, int activity_id, int count, bool ignore_quest_update = false); + void ResetTaskActivity(Client *client, int task_id, int activity_id); + void CancelTask(Client *client, int sequence_number, TaskType task_type, bool remove_from_db = true); + void CancelAllTasks(Client *client); + void RemoveTask(Client *client, int sequence_number, TaskType task_type); + void RemoveTaskByTaskID(Client *client, uint32 task_id); + bool UpdateTasksByNPC(Client *client, int activity_type, int npc_type_id); + void UpdateTasksOnKill(Client *client, int npc_type_id); + void UpdateTasksForItem(Client *client, ActivityType activity_type, int item_id, int count = 1); + void UpdateTasksOnExplore(Client *client, int explore_id); + bool UpdateTasksOnSpeakWith(Client *client, int npc_type_id); + bool UpdateTasksOnDeliver(Client *client, std::list &items, int cash, int npc_type_id); + void UpdateTasksOnTouch(Client *client, int zone_id); + void ProcessTaskProximities(Client *client, float x, float y, float z); + bool TaskOutOfTime(TaskType task_type, int index); + void TaskPeriodicChecks(Client *client); + void SendTaskHistory(Client *client, int task_index); + void RewardTask(Client *client, TaskInformation *task_information); + void EnableTask(int character_id, int task_count, int *task_list); + void DisableTask(int character_id, int task_count, int *task_list); + bool IsTaskEnabled(int task_id); + int EnabledTaskCount(int task_set_id); + int ActiveSpeakTask(int npc_type_id); + int ActiveSpeakActivity(int npc_type_id, int task_id); + int ActiveTasksInSet(int task_set_id); + int CompletedTasksInSet(int task_set_id); + bool HasSlotForTask(TaskInformation *task); + + inline bool HasFreeTaskSlot() { return m_active_task.task_id == TASKSLOTEMPTY; } + + friend class TaskManager; + +private: + bool UnlockActivities(int character_id, ClientTaskInformation &task_info); + void IncrementDoneCount( + Client *client, + TaskInformation *task_information, + int task_index, + int activity_id, + int count = 1, + bool ignore_quest_update = false + ); + + inline ClientTaskInformation *GetClientTaskInfo(TaskType task_type, int index) + { + ClientTaskInformation *info = nullptr; + switch (task_type) { + case TaskType::Task: + if (index == 0) { + info = &m_active_task; + } + break; + case TaskType::Shared: + break; + case TaskType::Quest: + if (index < MAXACTIVEQUESTS) { + info = &m_active_quests[index]; + } + break; + default: + break; + } + return info; + } + + union { // easier to loop over + struct { + ClientTaskInformation m_active_task; // only one + ClientTaskInformation m_active_quests[MAXACTIVEQUESTS]; + }; + ClientTaskInformation m_active_tasks[MAXACTIVEQUESTS + 1]; + }; + // Shared tasks should be limited to 1 as well + int m_active_task_count; + std::vector m_enabled_tasks; + std::vector m_completed_tasks; + int m_last_completed_task_loaded; + bool m_checked_touch_activities; +}; + + +#endif //EQEMU_TASK_CLIENT_STATE_H diff --git a/zone/task_goal_list_manager.cpp b/zone/task_goal_list_manager.cpp new file mode 100644 index 000000000..9a641c6eb --- /dev/null +++ b/zone/task_goal_list_manager.cpp @@ -0,0 +1,149 @@ +#include "../common/global_define.h" +#include "../common/misc_functions.h" +#include "../common/repositories/goallists_repository.h" +#include "../common/rulesys.h" +#include "client.h" +#include "mob.h" +#include "quest_parser_collection.h" +#include "task_goal_list_manager.h" +#include "tasks.h" +#include "zonedb.h" + +TaskGoalListManager::TaskGoalListManager() +{ + m_goal_lists_count = 0; +} + +TaskGoalListManager::~TaskGoalListManager() {} + +bool TaskGoalListManager::LoadLists() +{ + m_task_goal_lists.clear(); + m_goal_lists_count = 0; + + std::string query = "SELECT `listid`, COUNT(`entry`) FROM `goallists` GROUP by `listid` ORDER BY `listid`"; + auto results = content_db.QueryDatabase(query); + if (!results.Success()) { + return false; + } + + m_goal_lists_count = results.RowCount(); + LogTasks("Loaded [{}] GoalLists", m_goal_lists_count); + + m_task_goal_lists.reserve(m_goal_lists_count); + + int list_index = 0; + for (auto row = results.begin(); row != results.end(); ++row) { + int list_id = atoi(row[0]); + int list_size = atoi(row[1]); + + m_task_goal_lists.push_back({list_id, 0, 0}); + + m_task_goal_lists[list_index].GoalItemEntries.reserve(list_size); + + list_index++; + } + + auto goal_lists = GoallistsRepository::GetWhere(content_db, "TRUE ORDER BY listid, entry ASC"); + for (list_index = 0; list_index < m_goal_lists_count; list_index++) { + + int list_id = m_task_goal_lists[list_index].ListID; + + for (auto &entry: goal_lists) { + if (entry.listid == list_id) { + if (entry.entry < m_task_goal_lists[list_index].Min) { + m_task_goal_lists[list_index].Min = entry.entry; + } + + if (entry.entry > m_task_goal_lists[list_index].Max) { + m_task_goal_lists[list_index].Max = entry.entry; + } + + m_task_goal_lists[list_index].GoalItemEntries.push_back(entry.entry); + + LogTasksDetail( + "Goal list index [{}] loading list [{}] entry [{}]", + list_index, + list_id, + entry.entry + ); + } + } + } + + return true; + +} + +int TaskGoalListManager::GetListByID(int list_id) +{ + + // Find the list with the specified ListID and return the index + auto it = std::find_if( + m_task_goal_lists.begin(), + m_task_goal_lists.end(), + [list_id](const TaskGoalList_Struct &t) { return t.ListID == list_id; } + ); + + if (it == m_task_goal_lists.end()) { + return -1; + } + + return std::distance(m_task_goal_lists.begin(), it); +} + +int TaskGoalListManager::GetFirstEntry(int list_id) +{ + int list_by_id = GetListByID(list_id); + + if ((list_by_id < 0) || (list_by_id >= m_goal_lists_count)) { + return -1; + } + + if (m_task_goal_lists[list_by_id].GoalItemEntries.empty()) { + return -1; + } + + return m_task_goal_lists[list_by_id].GoalItemEntries[0]; +} + +std::vector TaskGoalListManager::GetListContents(int list_index) +{ + std::vector list_contents; + int list_by_id = GetListByID(list_index); + + if ((list_by_id < 0) || (list_by_id >= m_goal_lists_count)) { + return list_contents; + } + + list_contents = m_task_goal_lists[list_by_id].GoalItemEntries; + + return list_contents; +} + +bool TaskGoalListManager::IsInList(int list_id, int entry) +{ + Log(Logs::General, Logs::Tasks, "[UPDATE] TaskGoalListManager::IsInList(%i, %i)", list_id, entry); + + int list_index = GetListByID(list_id); + + if ((list_index < 0) || (list_index >= m_goal_lists_count)) { + return false; + } + + if ((entry < m_task_goal_lists[list_index].Min) || (entry > m_task_goal_lists[list_index].Max)) { + return false; + } + + int first_entry = 0; + auto &task = m_task_goal_lists[list_index]; + auto it = std::find(task.GoalItemEntries.begin(), task.GoalItemEntries.end(), entry); + + if (it == task.GoalItemEntries.end()) { + return false; + } + + Log(Logs::General, Logs::Tasks, "[UPDATE] TaskGoalListManager::IsInList(%i, %i) returning true", list_index, entry); + + return true; +} diff --git a/zone/task_goal_list_manager.h b/zone/task_goal_list_manager.h new file mode 100644 index 000000000..11146f6e3 --- /dev/null +++ b/zone/task_goal_list_manager.h @@ -0,0 +1,37 @@ +#ifndef EQEMU_TASK_GOAL_LIST_MANAGER_H +#define EQEMU_TASK_GOAL_LIST_MANAGER_H + +#include "tasks.h" +#include "../common/types.h" +#include +#include +#include +#include + +struct TaskGoalList_Struct { + int ListID; + int Min, Max; + std::vector GoalItemEntries; +}; + +// This is used for handling lists, loading them from the database, searching them. +// Used for lists of NPCs to kill, items to loot, etc, as well as lists of items to +// reward the player with on completion of the task. +class TaskGoalListManager { + +public: + TaskGoalListManager(); + ~TaskGoalListManager(); + bool LoadLists(); + int GetListByID(int list_id); + bool IsInList(int list_id, int entry); + int GetFirstEntry(int list_id); + std::vector GetListContents(int list_index); + +private: + std::vector m_task_goal_lists; + int m_goal_lists_count; +}; + + +#endif //EQEMU_TASK_GOAL_LIST_MANAGER_H diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp new file mode 100644 index 000000000..7ba251840 --- /dev/null +++ b/zone/task_manager.cpp @@ -0,0 +1,1656 @@ +#include "../common/global_define.h" +#include "../common/misc_functions.h" +#include "../common/repositories/character_activities_repository.h" +#include "../common/repositories/character_tasks_repository.h" +#include "../common/repositories/completed_tasks_repository.h" +#include "../common/repositories/task_activities_repository.h" +#include "../common/repositories/tasks_repository.h" +#include "../common/repositories/tasksets_repository.h" +#include "client.h" +#include "string_ids.h" +#include "task_manager.h" + +TaskManager::TaskManager() +{ + for (auto &task : m_task_data) { + task = nullptr; + } +} + +TaskManager::~TaskManager() +{ + for (auto &task : m_task_data) { + if (task != nullptr) { + safe_delete(task); + } + } +} + +bool TaskManager::LoadTaskSets() +{ + // Clear all task sets in memory. Done so we can reload them on the fly if required by just calling + // this method again. + for (auto &task_set : m_task_sets) { + task_set.clear(); + } + + auto rows = TasksetsRepository::GetWhere( + content_db, + fmt::format( + "`id` > 0 AND `id` < {} AND `taskid` >= 0 AND `taskid` < {} ORDER BY `id`, `taskid` ASC", + MAXTASKSETS, + MAXTASKS + ) + ); + + for (auto &task_set: rows) { + m_task_sets[task_set.id].push_back(task_set.taskid); + LogTasksDetail("[LoadTaskSets] Adding task_id [{}] to task_set [{}]", task_set.taskid, task_set.id); + } + + return true; +} + +void TaskManager::ReloadGoalLists() +{ + if (!m_goal_list_manager.LoadLists()) { + Log(Logs::Detail, Logs::Tasks, "TaskManager::LoadTasks LoadLists failed"); + } +} + +bool TaskManager::LoadTasks(int single_task) +{ + std::string task_query_filter = fmt::format("id = {}", single_task); + std::string query; + if (single_task == 0) { + if (!m_goal_list_manager.LoadLists()) { + LogTasks("[TaskManager::LoadTasks] LoadLists failed"); + } + + if (!LoadTaskSets()) { + LogTasks("[TaskManager::LoadTasks] LoadTaskSets failed"); + } + + task_query_filter = fmt::format("id < {}", MAXTASKS); + } + + // load task level data + auto repo_tasks = TasksRepository::GetWhere(content_db, task_query_filter); + + for (auto &task: repo_tasks) { + int task_id = task.id; + + if ((task_id <= 0) || (task_id >= MAXTASKS)) { + // This shouldn't happen, as the SELECT is bounded by MAXTASKS + LogError("[TASKS]Task ID [{}] out of range while loading tasks from database", task_id); + continue; + } + + // load task data + m_task_data[task_id] = new TaskInformation; + m_task_data[task_id]->type = static_cast(task.type); + m_task_data[task_id]->duration = task.duration; + m_task_data[task_id]->duration_code = static_cast(task.duration_code); + m_task_data[task_id]->title = task.title; + m_task_data[task_id]->description = task.description; + m_task_data[task_id]->reward = task.reward; + m_task_data[task_id]->reward_id = task.rewardid; + m_task_data[task_id]->cash_reward = task.cashreward; + m_task_data[task_id]->experience_reward = task.xpreward; + m_task_data[task_id]->reward_method = (TaskMethodType) task.rewardmethod; + m_task_data[task_id]->faction_reward = task.faction_reward; + m_task_data[task_id]->min_level = task.minlevel; + m_task_data[task_id]->max_level = task.maxlevel; + m_task_data[task_id]->repeatable = task.repeatable; + m_task_data[task_id]->completion_emote = task.completion_emote; + m_task_data[task_id]->activity_count = 0; + m_task_data[task_id]->sequence_mode = ActivitiesSequential; + m_task_data[task_id]->last_step = 0; + + LogTasksDetail( + "[LoadTasks] (Task) task_id [{}] type [{}] duration [{}] duration_code [{}] title [{}] description [{}] " + " reward [{}] rewardid [{}] cashreward [{}] xpreward [{}] rewardmethod [{}] faction_reward [{}] minlevel [{}] " + " maxlevel [{}] repeatable [{}] completion_emote [{}] ", + task.id, + task.type, + task.duration, + task.duration_code, + task.title, + task.description, + task.reward, + task.rewardid, + task.cashreward, + task.xpreward, + task.rewardmethod, + task.faction_reward, + task.minlevel, + task.maxlevel, + task.repeatable, + task.completion_emote + ); + } + + LogTasks("Loaded [{}] Tasks", repo_tasks.size()); + + std::string activities_query_filter = fmt::format( + "taskid = {} and activityid < {} ORDER BY taskid, activityid ASC", + single_task, + MAXACTIVITIESPERTASK + ); + + // if loading only a single task + if (single_task == 0) { + activities_query_filter = fmt::format( + "taskid < {} and activityid < {} ORDER BY taskid, activityid ASC", + MAXTASKS, + MAXACTIVITIESPERTASK + ); + } + + // load activity data + auto task_activities = TaskActivitiesRepository::GetWhere(content_db, activities_query_filter); + for (auto &task_activity: task_activities) { + int task_id = task_activity.taskid; + int step = task_activity.step; + int activity_id = task_activity.activityid; + + // create pointer to activity data since declarations get unruly long + int activity_index = m_task_data[task_id]->activity_count; + ActivityInformation *activity_data = &m_task_data[task_id]->activity_information[activity_index]; + + if ((task_id <= 0) || (task_id >= MAXTASKS) || (activity_id < 0) || (activity_id >= MAXACTIVITIESPERTASK)) { + + // This shouldn't happen, as the SELECT is bounded by MAXTASKS + LogTasks( + "[LoadTasks] Error: Task or activity_information ID ([{}], [{}]) out of range while loading activities from database", + task_id, + activity_id + ); + continue; + } + + if (m_task_data[task_id] == nullptr) { + LogTasks( + "[LoadTasks] Error: activity_information for non-existent task ([{}], [{}]) while loading activities from database", + task_id, + activity_id + ); + continue; + } + + m_task_data[task_id]->activity_information[m_task_data[task_id]->activity_count].step_number = step; + + if (step != 0) { + m_task_data[task_id]->sequence_mode = ActivitiesStepped; + } + + if (step > m_task_data[task_id]->last_step) { + m_task_data[task_id]->last_step = step; + } + + // Task Activities MUST be numbered sequentially from 0. If not, log an error + // and set the task to nullptr. Subsequent activities for this task will raise + // ERR_NOTASK errors. + // Change to (activityID != (Tasks[taskID]->activity_count + 1)) to index from 1 + if (activity_id != m_task_data[task_id]->activity_count) { + LogTasks( + "[LoadTasks] Error: Activities for Task [{}] (activity_id [{}]) are not sequential starting at 0. Not loading task ", + task_id, + activity_id + ); + m_task_data[task_id] = nullptr; + continue; + } + + // set activity data + activity_data->activity_type = task_activity.activitytype; + activity_data->target_name = task_activity.target_name; + activity_data->item_list = task_activity.item_list; + activity_data->skill_list = task_activity.skill_list; + activity_data->skill_id = std::stoi(task_activity.skill_list); // for older clients + activity_data->spell_list = task_activity.spell_list; + activity_data->spell_id = std::stoi(task_activity.spell_list); // for older clients + activity_data->description_override = task_activity.description_override; + activity_data->goal_id = task_activity.goalid; + activity_data->goal_method = (TaskMethodType) task_activity.goalmethod; + activity_data->goal_count = task_activity.goalcount; + activity_data->deliver_to_npc = task_activity.delivertonpc; + + // zones + activity_data->zones = task_activity.zones; + auto zones = SplitString( + task_activity.zones, + ';' + ); + + for (auto &&e : zones) { + activity_data->zone_ids.push_back(std::stoi(e)); + } + + activity_data->optional = task_activity.optional; + + LogTasksDetail( + "[LoadTasks] (Activity) task_id [{}] activity_id [{}] slot [{}] activity_type [{}] goal_id [{}] goal_method [{}] goal_count [{}] zones [{}]" + " target_name [{}] item_list [{}] skill_list [{}] spell_list [{}] description_override [{}]", + task_id, + activity_id, + m_task_data[task_id]->activity_count, + activity_data->activity_type, + activity_data->goal_id, + activity_data->goal_method, + activity_data->goal_count, + activity_data->zones.c_str(), + activity_data->target_name.c_str(), + activity_data->item_list.c_str(), + activity_data->skill_list.c_str(), + activity_data->spell_list.c_str(), + activity_data->description_override.c_str() + ); + + m_task_data[task_id]->activity_count++; + } + + LogTasks("Loaded [{}] Task Activities", task_activities.size()); + + return true; +} + +bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_state) +{ + // I am saving the slot in the ActiveTasks table, because unless a Task is cancelled/completed, the client + // doesn't seem to like tasks moving slots between zoning and you can end up with 'bogus' activities if the task + // previously in that slot had more activities than the one now occupying it. Hopefully retaining the slot + // number for the duration of a session will overcome this. + if (!client || !client_task_state) { + return false; + } + + const char *ERR_MYSQLERROR = "[TASKS]Error in TaskManager::SaveClientState %s"; + + int character_id = client->CharacterID(); + + LogTasks("[SaveClientState] character_id [{}]", character_id); + + if (client_task_state->m_active_task_count > 0 || + client_task_state->m_active_task.task_id != TASKSLOTEMPTY) { // TODO: tasks + for (auto &active_task : client_task_state->m_active_tasks) { + int task_id = active_task.task_id; + if (task_id == TASKSLOTEMPTY) { + continue; + } + + int slot = active_task.slot; + if (active_task.updated) { + + LogTasks( + "[SaveClientState] character_id [{}] updating task_index [{}] task_id [{}]", + character_id, + slot, + task_id + ); + + std::string query = StringFormat( + "REPLACE INTO character_tasks (charid, taskid, slot, type, acceptedtime) " + "VALUES (%i, %i, %i, %i, %i)", + character_id, + task_id, + slot, + static_cast(m_task_data[task_id]->type), + active_task.accepted_time + ); + + auto results = database.QueryDatabase(query); + if (!results.Success()) { + LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str()); + } + else { + active_task.updated = false; + } + } + + std::string query = + "REPLACE INTO character_activities (charid, taskid, activityid, donecount, completed) " + "VALUES "; + + int updated_activity_count = 0; + + for (int activity_index = 0; activity_index < m_task_data[task_id]->activity_count; ++activity_index) { + if (!active_task.activity[activity_index].updated) { + continue; + } + + LogTasks( + "[SaveClientState] Updating activity character_id [{}] updating task_index [{}] task_id [{}] activity_index [{}]", + character_id, + slot, + task_id, + activity_index + ); + + if (updated_activity_count == 0) { + query += + StringFormat( + "(%i, %i, %i, %i, %i)", character_id, task_id, activity_index, + active_task.activity[activity_index].done_count, + active_task.activity[activity_index].activity_state == + ActivityCompleted + ); + } + else { + query += + StringFormat( + ", (%i, %i, %i, %i, %i)", character_id, task_id, activity_index, + active_task.activity[activity_index].done_count, + active_task.activity[activity_index].activity_state == + ActivityCompleted + ); + } + + updated_activity_count++; + } + + if (updated_activity_count == 0) { + continue; + } + + auto results = database.QueryDatabase(query); + + if (!results.Success()) { + LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str()); + continue; + } + + active_task.updated = false; + for (int activity_index = 0; + activity_index < m_task_data[task_id]->activity_count; + ++activity_index) + active_task.activity[activity_index].updated = false; + } + } + + if (!RuleB(TaskSystem, RecordCompletedTasks) || + (client_task_state->m_completed_tasks.size() <= (unsigned int) client_task_state->m_last_completed_task_loaded)) { + client_task_state->m_last_completed_task_loaded = client_task_state->m_completed_tasks.size(); + return true; + } + + const char *completed_task_query = "REPLACE INTO completed_tasks (charid, completedtime, taskid, activityid) " + "VALUES (%i, %i, %i, %i)"; + + for (unsigned int task_index = client_task_state->m_last_completed_task_loaded; + task_index < client_task_state->m_completed_tasks.size(); + task_index++) { + + int task_id = client_task_state->m_completed_tasks[task_index].task_id; + + if ((task_id <= 0) || (task_id >= MAXTASKS) || (m_task_data[task_id] == nullptr)) { + continue; + } + + // First we save a record with an activity_id of -1. + // This indicates this task was completed at the given time. We infer that all + // none optional activities were completed. + // + std::string query = StringFormat( + completed_task_query, + character_id, + client_task_state->m_completed_tasks[task_index].completed_time, + task_id, + -1 + ); + + auto results = database.QueryDatabase(query); + if (!results.Success()) { + LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str()); + continue; + } + + // If the Rule to record non-optional task completion is not enabled, don't save it + if (!RuleB(TaskSystem, RecordCompletedOptionalActivities)) { + continue; + } + + // Insert one record for each completed optional task. + for (int activity_id = 0; activity_id < m_task_data[task_id]->activity_count; activity_id++) { + if (!m_task_data[task_id]->activity_information[activity_id].optional || + !client_task_state->m_completed_tasks[task_index].activity_done[activity_id]) { + continue; + } + + query = StringFormat( + completed_task_query, + character_id, + client_task_state->m_completed_tasks[task_index].completed_time, + task_id, activity_id + ); + + results = database.QueryDatabase(query); + if (!results.Success()) { + LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str()); + } + } + } + + client_task_state->m_last_completed_task_loaded = client_task_state->m_completed_tasks.size(); + return true; +} + +int TaskManager::FirstTaskInSet(int task_set) +{ + if ((task_set <= 0) || (task_set >= MAXTASKSETS)) { + return 0; + } + + if (m_task_sets[task_set].empty()) { + return 0; + } + + auto iterator = m_task_sets[task_set].begin(); + while (iterator != m_task_sets[task_set].end()) { + if ((*iterator) > 0) { + return (*iterator); + } + ++iterator; + } + + return 0; +} + +int TaskManager::LastTaskInSet(int task_set) +{ + if ((task_set <= 0) || (task_set >= MAXTASKSETS)) { + return 0; + } + + if (m_task_sets[task_set].empty()) { + return 0; + } + + return m_task_sets[task_set][m_task_sets[task_set].size() - 1]; +} + +int TaskManager::NextTaskInSet(int task_set, int task_id) +{ + if ((task_set <= 0) || (task_set >= MAXTASKSETS)) { + return 0; + } + + if (m_task_sets[task_set].empty()) { + return 0; + } + + for (int i : m_task_sets[task_set]) { + if (i > task_id) { + return i; + } + } + + return 0; +} + +bool TaskManager::ValidateLevel(int task_id, int player_level) +{ + if (m_task_data[task_id] == nullptr) { + return false; + } + + if (m_task_data[task_id]->min_level && (player_level < m_task_data[task_id]->min_level)) { + return false; + } + + if (m_task_data[task_id]->max_level && (player_level > m_task_data[task_id]->max_level)) { + return false; + } + + return true; +} + +std::string TaskManager::GetTaskName(uint32 task_id) +{ + if (task_id > 0 && task_id < MAXTASKS) { + if (m_task_data[task_id] != nullptr) { + return m_task_data[task_id]->title; + } + } + + return std::string(); +} + +TaskType TaskManager::GetTaskType(uint32 task_id) +{ + if (task_id > 0 && task_id < MAXTASKS) { + if (m_task_data[task_id] != nullptr) { + return m_task_data[task_id]->type; + } + } + return TaskType::Task; +} + +void TaskManager::TaskSetSelector(Client *client, ClientTaskState *client_task_state, Mob *mob, int task_set_id) +{ + int task_list[MAXCHOOSERENTRIES]; + int task_list_index = 0; + int player_level = client->GetLevel(); + + LogTasks( + "TaskSetSelector called for task_set_id [{}] EnableTaskSize is [{}]", + task_set_id, + client_task_state->m_enabled_tasks.size() + ); + + if (task_set_id <= 0 || task_set_id >= MAXTASKSETS) { + return; + } + + if (m_task_sets[task_set_id].empty()) { + // I think this is suppose to be yellow + mob->SayString( + client, + Chat::Yellow, + MAX_ACTIVE_TASKS, + client->GetName() + ); + return; + } + + bool all_enabled = false; + + // A task_id of 0 in a TaskSet indicates that all Tasks in the set are enabled for all players. + if (m_task_sets[task_set_id][0] == 0) { + LogTasks("[TaskSetSelector] TaskSets[{}][0] == 0. All Tasks in Set enabled.", task_set_id); + all_enabled = true; + } + + auto iterator = m_task_sets[task_set_id].begin(); + if (all_enabled) { + ++iterator; + } // skip first when all enabled since it's useless data + + while (iterator != m_task_sets[task_set_id].end() && task_list_index < MAXCHOOSERENTRIES) { + auto task = *iterator; + // verify level, we're not currently on it, repeatable status, if it's a (shared) task + // we aren't currently on another, and if it's enabled if not all_enabled + if ((all_enabled || client_task_state->IsTaskEnabled(task)) && ValidateLevel(task, player_level) && + !client_task_state->IsTaskActive(task) && client_task_state->HasSlotForTask(m_task_data[task]) && + // this slot checking is a bit silly, but we allow mixing of task types ... + (IsTaskRepeatable(task) || !client_task_state->IsTaskCompleted(task))) { + task_list[task_list_index++] = task; + } + + ++iterator; + } + + if (task_list_index > 0) { + SendTaskSelector(client, mob, task_list_index, task_list); + } + else { + // TODO: check color, I think this might be only for (Shared) Tasks, w/e -- think should be yellow + mob->SayString( + client, + Chat::Yellow, + MAX_ACTIVE_TASKS, + client->GetName() + ); + } +} + +// unlike the non-Quest version of this function, it does not check enabled, that is assumed the responsibility of the quest to handle +// we do however still want it to check the other stuff like level, active, room, etc +void TaskManager::TaskQuestSetSelector( + Client *client, + ClientTaskState *client_task_state, + Mob *mob, + int count, + int *tasks +) +{ + int task_list[MAXCHOOSERENTRIES]; + int task_list_index = 0; + int player_level = client->GetLevel(); + + LogTasks("[UPDATE] TaskQuestSetSelector called for array size [{}]", count); + + if (count <= 0) { + return; + } + + for (int i = 0; i < count; ++i) { + auto task = tasks[i]; + // verify level, we're not currently on it, repeatable status, if it's a (shared) task + // we aren't currently on another, and if it's enabled if not all_enabled + if (ValidateLevel(task, player_level) && !client_task_state->IsTaskActive(task) && + client_task_state->HasSlotForTask(m_task_data[task]) && + // this slot checking is a bit silly, but we allow mixing of task types ... + (IsTaskRepeatable(task) || !client_task_state->IsTaskCompleted(task))) { + task_list[task_list_index++] = task; + } + } + + if (task_list_index > 0) { + SendTaskSelector(client, mob, task_list_index, task_list); + } + else { + // TODO: check color, I think this might be only for (Shared) Tasks, w/e -- think should be yellow + mob->SayString( + client, + Chat::Yellow, + MAX_ACTIVE_TASKS, + client->GetName() + ); + } +} + +// sends task selector to client +void TaskManager::SendTaskSelector(Client *client, Mob *mob, int task_count, int *task_list) +{ + if (client->ClientVersion() >= EQ::versions::ClientVersion::RoF) { + SendTaskSelectorNew(client, mob, task_count, task_list); + return; + } + // Titanium OpCode: 0x5e7c + LogTasks("TaskSelector for [{}] Tasks", task_count); + int player_level = client->GetLevel(); + + // Check if any of the tasks exist + for (int i = 0; i < task_count; i++) { + if (m_task_data[task_list[i]] != nullptr) { + break; + } + } + + int valid_task_count = 0; + + for (int i = 0; i < task_count; i++) { + if (!ValidateLevel(task_list[i], player_level)) { + continue; + } + if (client->IsTaskActive(task_list[i])) { + continue; + } + if (!IsTaskRepeatable(task_list[i]) && client->IsTaskCompleted(task_list[i])) { + continue; + } + + valid_task_count++; + } + + if (valid_task_count == 0) { + return; + } + + SerializeBuffer buf(50 * valid_task_count); + + buf.WriteUInt32(valid_task_count); + buf.WriteUInt32(2); // task type, live doesn't let you send more than one type, but we do? + buf.WriteUInt32(mob->GetID()); + + for (int task_index = 0; task_index < task_count; task_index++) { + if (!ValidateLevel(task_list[task_index], player_level)) { + continue; + } + if (client->IsTaskActive(task_list[task_index])) { + continue; + } + if (!IsTaskRepeatable(task_list[task_index]) && client->IsTaskCompleted(task_list[task_index])) { + continue; + } + + buf.WriteUInt32(task_list[task_index]); // task_id + + // affects color, difficulty? + if (client->ClientVersion() != EQ::versions::ClientVersion::Titanium) { + buf.WriteFloat(1.0f); + } + buf.WriteUInt32(m_task_data[task_list[task_index]]->duration); + buf.WriteUInt32(static_cast(m_task_data[task_list[task_index]]->duration_code)); + + buf.WriteString(m_task_data[task_list[task_index]]->title); // max 64 with null + buf.WriteString(m_task_data[task_list[task_index]]->description); // max 4000 with null + + // Has reward set flag + if (client->ClientVersion() != EQ::versions::ClientVersion::Titanium) { + buf.WriteUInt8(0); + } + + buf.WriteUInt32(m_task_data[task_list[task_index]]->activity_count); + + for (int activity_index = 0; + activity_index < m_task_data[task_list[task_index]]->activity_count; + ++activity_index) { + buf.WriteUInt32(activity_index); // ActivityNumber + auto &activity = m_task_data[task_list[task_index]]->activity_information[activity_index]; + buf.WriteUInt32(activity.activity_type); + buf.WriteUInt32(0); // solo, group, raid? + buf.WriteString(activity.target_name); // max length 64, "target name" so like loot x foo from bar (this is bar) + buf.WriteString(activity.item_list); // max length 64 in these clients + buf.WriteUInt32(activity.goal_count); + buf.WriteInt32(activity.skill_id); + buf.WriteInt32(activity.spell_id); + buf.WriteInt32(activity.zone_ids.empty() ? 0 : activity.zone_ids.front()); + buf.WriteString(activity.description_override); + } + } + + auto outapp = new EQApplicationPacket(OP_OpenNewTasksWindow, buf); + + client->QueuePacket(outapp); + safe_delete(outapp); +} + +void TaskManager::SendTaskSelectorNew(Client *client, Mob *mob, int task_count, int *task_list) +{ + LogTasks("SendTaskSelectorNew for [{}] Tasks", task_count); + + int player_level = client->GetLevel(); + + // Check if any of the tasks exist + for (int i = 0; i < task_count; i++) { + if (m_task_data[task_list[i]] != nullptr) { + break; + } + } + + int valid_tasks_count = 0; + for (int task_index = 0; task_index < task_count; task_index++) { + if (!ValidateLevel(task_list[task_index], player_level)) { + continue; + } + if (client->IsTaskActive(task_list[task_index])) { + continue; + } + if (!IsTaskRepeatable(task_list[task_index]) && client->IsTaskCompleted(task_list[task_index])) { + continue; + } + + valid_tasks_count++; + } + + if (valid_tasks_count == 0) { + return; + } + + SerializeBuffer buf(50 * valid_tasks_count); + + buf.WriteUInt32(valid_tasks_count); // TaskCount + buf.WriteUInt32(2); // Type, valid values: 0-3. 0 = Task, 1 = Shared Task, 2 = Quest, 3 = ??? -- should fix maybe some day, but we let more than 1 type through :P + // so I guess an NPC can only offer one type of quests or we can only open a selection with one type :P (so quest call can tell us I guess) + // this is also sent in OP_TaskDescription + buf.WriteUInt32(mob->GetID()); // TaskGiver + + for (int i = 0; i < task_count; i++) { // max 40 + if (!ValidateLevel(task_list[i], player_level)) { + continue; + } + if (client->IsTaskActive(task_list[i])) { + continue; + } + if (!IsTaskRepeatable(task_list[i]) && client->IsTaskCompleted(task_list[i])) { + continue; + } + + buf.WriteUInt32(task_list[i]); // task_id + buf.WriteFloat(1.0f); // affects color, difficulty? + buf.WriteUInt32(m_task_data[task_list[i]]->duration); + buf.WriteUInt32(static_cast(m_task_data[task_list[i]]->duration_code)); // 1 = Short, 2 = Medium, 3 = Long, anything else Unlimited + + buf.WriteString(m_task_data[task_list[i]]->title); // max 64 with null + buf.WriteString(m_task_data[task_list[i]]->description); // max 4000 with null + + buf.WriteUInt8(0); // Has reward set flag + buf.WriteUInt32(m_task_data[task_list[i]]->activity_count); // activity_count + + for (int j = 0; j < m_task_data[task_list[i]]->activity_count; ++j) { + buf.WriteUInt32(j); // ActivityNumber + auto &activity = m_task_data[task_list[i]]->activity_information[j]; + buf.WriteUInt32(activity.activity_type); // ActivityType + buf.WriteUInt32(0); // solo, group, raid? + buf.WriteString(activity.target_name); // max length 64, "target name" so like loot x foo from bar (this is bar) + + // this string is item names + buf.WriteLengthString(activity.item_list); + + buf.WriteUInt32(activity.goal_count); // GoalCount + + // this string is skill IDs? probably one of the "use on" tasks + buf.WriteLengthString(activity.skill_list); + + // this string is spell IDs? probably one of the "use on" tasks + buf.WriteLengthString(activity.spell_list); + + //buf.WriteString(itoa(Tasks[TaskList[i]]->activity_information[activity_id].ZoneID)); + buf.WriteString(activity.zones); // Zone number in ascii max length 64, can be multiple with separated by ; + buf.WriteString(activity.description_override); // max length 128 -- overrides the automatic descriptions + // this doesn't appear to be shown to the client at all and isn't the same as zones ... defaults to '0' though + buf.WriteString(activity.zones); // Zone number in ascii max length 64, probably can be separated by ; too, haven't found it used + } + } + + auto outapp = new EQApplicationPacket(OP_OpenNewTasksWindow, buf); + + client->QueuePacket(outapp); + safe_delete(outapp); +} + +int TaskManager::GetActivityCount(int task_id) +{ + if ((task_id > 0) && (task_id < MAXTASKS)) { + if (m_task_data[task_id]) { return m_task_data[task_id]->activity_count; } + } + + return 0; +} + +void TaskManager::ExplainTask(Client *client, int task_id) +{ + + // TODO: This method is not finished (hardly started). It was intended to + // explain in English, what each activity_information did, conditions for step unlocking, etc. + // + return; + + if (!client) { return; } + + if ((task_id <= 0) || (task_id >= MAXTASKS)) { + client->Message(Chat::White, "task_id out-of-range."); + return; + } + + if (m_task_data[task_id] == nullptr) { + client->Message(Chat::White, "Task does not exist."); + return; + } + + char explanation[1000], *ptr; + client->Message(Chat::White, "Task %4i: title: %s", task_id, m_task_data[task_id]->description.c_str()); + client->Message(Chat::White, "%3i Activities", m_task_data[task_id]->activity_count); + ptr = explanation; + for (int i = 0; i < m_task_data[task_id]->activity_count; i++) { + + sprintf(ptr, "Act: %3i: ", i); + ptr = ptr + strlen(ptr); + switch (m_task_data[task_id]->activity_information[i].activity_type) { + case ActivityDeliver: + sprintf(ptr, "Deliver"); + break; + } + + } +} + +bool TaskManager::IsTaskRepeatable(int task_id) +{ + if ((task_id <= 0) || (task_id >= MAXTASKS)) { + return false; + } + + TaskInformation *task_data = task_manager->m_task_data[task_id]; + if (task_data == nullptr) { + return false; + } + + return task_data->repeatable; +} + +void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *client_task_state) +{ + int packet_length = 4; + + //vector::const_iterator iterator; + // The client only display the first 50 Completed Tasks send, so send the 50 most recent + int first_task_to_send = 0; + int last_task_to_send = client_task_state->m_completed_tasks.size(); + + if (client_task_state->m_completed_tasks.size() > 50) { + first_task_to_send = client_task_state->m_completed_tasks.size() - 50; + } + + LogTasks( + "[SendCompletedTasksToClient] completed task count [{}] first tank to send is [{}] last is [{}]", + client_task_state->m_completed_tasks.size(), + first_task_to_send, + last_task_to_send + ); + + /* + for(iterator=activity_state->CompletedTasks.begin(); iterator!=activity_state->CompletedTasks.end(); iterator++) { + int task_id = (*iterator).task_id; + if(Tasks[task_id] == nullptr) continue; + PacketLength = PacketLength + 8 + strlen(Tasks[task_id]->title) + 1; + } + */ + for (int i = first_task_to_send; i < last_task_to_send; i++) { + int TaskID = client_task_state->m_completed_tasks[i].task_id; + if (m_task_data[TaskID] == nullptr) { continue; } + packet_length = packet_length + 8 + m_task_data[TaskID]->title.size() + 1; + } + + auto outapp = new EQApplicationPacket(OP_CompletedTasks, packet_length); + char *buf = (char *) outapp->pBuffer; + + //*(uint32 *)buf = activity_state->CompletedTasks.size(); + *(uint32 *) buf = last_task_to_send - first_task_to_send; + buf = buf + 4; + //for(iterator=activity_state->CompletedTasks.begin(); iterator!=activity_state->CompletedTasks.end(); iterator++) { + // int task_id = (*iterator).task_id; + for (int i = first_task_to_send; i < last_task_to_send; i++) { + int task_id = client_task_state->m_completed_tasks[i].task_id; + if (m_task_data[task_id] == nullptr) { continue; } + *(uint32 *) buf = task_id; + buf = buf + 4; + + sprintf(buf, "%s", m_task_data[task_id]->title.c_str()); + buf = buf + strlen(buf) + 1; + //*(uint32 *)buf = (*iterator).CompletedTime; + *(uint32 *) buf = client_task_state->m_completed_tasks[i].completed_time; + buf = buf + 4; + } + + c->QueuePacket(outapp); + safe_delete(outapp); +} + +void TaskManager::SendTaskActivityShort(Client *client, int task_id, int activity_id, int client_task_index) +{ + // This activity_information Packet is sent for activities that have not yet been unlocked and appear as ??? + // in the client. + + TaskActivityShort_Struct *task_activity_short; + if (client->ClientVersionBit() & EQ::versions::maskRoFAndLater) { + auto outapp = new EQApplicationPacket(OP_TaskActivity, 25); + outapp->WriteUInt32(client_task_index); + outapp->WriteUInt32(static_cast(m_task_data[task_id]->type)); + outapp->WriteUInt32(task_id); + outapp->WriteUInt32(activity_id); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0xffffffff); + outapp->WriteUInt8(0); + client->FastQueuePacket(&outapp); + + return; + } + + auto outapp = new EQApplicationPacket(OP_TaskActivity, sizeof(TaskActivityShort_Struct)); + + task_activity_short = (TaskActivityShort_Struct *) outapp->pBuffer; + task_activity_short->TaskSequenceNumber = client_task_index; + task_activity_short->unknown2 = static_cast(m_task_data[task_id]->type); + task_activity_short->TaskID = task_id; + task_activity_short->ActivityID = activity_id; + task_activity_short->unknown3 = 0x000000; + task_activity_short->ActivityType = 0xffffffff; + task_activity_short->unknown4 = 0x00000000; + + client->QueuePacket(outapp); + safe_delete(outapp); +} + +void TaskManager::SendTaskActivityLong( + Client *client, + int task_id, + int activity_id, + int client_task_index, + bool optional, + bool task_complete +) +{ + + if (client->ClientVersion() >= EQ::versions::ClientVersion::RoF) { + SendTaskActivityNew(client, task_id, activity_id, client_task_index, optional, task_complete); + return; + } + + SerializeBuffer buf(100); + + buf.WriteUInt32(client_task_index); + buf.WriteUInt32(static_cast(m_task_data[task_id]->type)); + buf.WriteUInt32(task_id); + buf.WriteUInt32(activity_id); + buf.WriteUInt32(0); // unknown3 + + // We send our 'internal' types as ActivityCastOn. text3 should be set to the activity_information description, so it makes + // no difference to the client. All activity_information updates will be done based on our interal activity_information types. + if ((m_task_data[task_id]->activity_information[activity_id].activity_type > 0) && + m_task_data[task_id]->activity_information[activity_id].activity_type < 100) { + buf.WriteUInt32(m_task_data[task_id]->activity_information[activity_id].activity_type); + } + else { + buf.WriteUInt32(ActivityCastOn); + } // w/e! + + buf.WriteUInt32(optional); + buf.WriteUInt32(0); // solo, group, raid + + buf.WriteString(m_task_data[task_id]->activity_information[activity_id].target_name); // target name string + buf.WriteString(m_task_data[task_id]->activity_information[activity_id].item_list); // item name list + + if (m_task_data[task_id]->activity_information[activity_id].activity_type != ActivityGiveCash) { + buf.WriteUInt32(m_task_data[task_id]->activity_information[activity_id].goal_count); + } + else { + // For our internal type GiveCash, where the goal count has the amount of cash that must be given, + // we don't want the donecount and goalcount fields cluttered up with potentially large numbers, so we just + // send a goalcount of 1, and a bit further down, a donecount of 1 if the activity_information is complete, 0 otherwise. + // The text3 field should decribe the exact activity_information goal, e.g. give 3500gp to Hasten Bootstrutter. + buf.WriteUInt32(1); + } + + buf.WriteUInt32(m_task_data[task_id]->activity_information[activity_id].skill_id); + buf.WriteUInt32(m_task_data[task_id]->activity_information[activity_id].spell_id); + buf.WriteUInt32( + m_task_data[task_id]->activity_information[activity_id].zone_ids.empty() ? 0 + : m_task_data[task_id]->activity_information[activity_id].zone_ids.front()); + buf.WriteUInt32(0); + + buf.WriteString(m_task_data[task_id]->activity_information[activity_id].description_override); + + if (m_task_data[task_id]->activity_information[activity_id].activity_type != ActivityGiveCash) { + buf.WriteUInt32(client->GetTaskActivityDoneCount(m_task_data[task_id]->type, client_task_index, activity_id)); + } + else { + // For internal activity_information types, done_count is either 1 if the activity_information is complete, 0 otherwise. + buf.WriteUInt32((client->GetTaskActivityDoneCount(m_task_data[task_id]->type, client_task_index, activity_id) >= + m_task_data[task_id]->activity_information[activity_id].goal_count)); + } + + buf.WriteUInt32(1); // unknown + + auto outapp = new EQApplicationPacket(OP_TaskActivity, buf); + + client->QueuePacket(outapp); + safe_delete(outapp); + +} + +// Used only by RoF+ Clients +void TaskManager::SendTaskActivityNew( + Client *client, + int task_id, + int activity_id, + int client_task_index, + bool optional, + bool task_complete +) +{ + SerializeBuffer buf(100); + + buf.WriteUInt32(client_task_index); // TaskSequenceNumber + buf.WriteUInt32(static_cast(m_task_data[task_id]->type)); // task type + buf.WriteUInt32(task_id); + buf.WriteUInt32(activity_id); + buf.WriteUInt32(0); // unknown3 + + // We send our 'internal' types as ActivityCastOn. text3 should be set to the activity_information description, so it makes + // no difference to the client. All activity_information updates will be done based on our interal activity_information types. + if ((m_task_data[task_id]->activity_information[activity_id].activity_type > 0) && + m_task_data[task_id]->activity_information[activity_id].activity_type < 100) { + buf.WriteUInt32(m_task_data[task_id]->activity_information[activity_id].activity_type); + } + else { + buf.WriteUInt32(ActivityCastOn); + } // w/e! + + buf.WriteUInt8(optional); + buf.WriteUInt32(0); // solo, group, raid + + // One of these unknown fields maybe related to the 'Use On' activity_information types + buf.WriteString(m_task_data[task_id]->activity_information[activity_id].target_name); // target name string + + buf.WriteLengthString(m_task_data[task_id]->activity_information[activity_id].item_list); // item name list + + // Goal Count + if (m_task_data[task_id]->activity_information[activity_id].activity_type != ActivityGiveCash) { + buf.WriteUInt32(m_task_data[task_id]->activity_information[activity_id].goal_count); + } + else { + buf.WriteUInt32(1); + } // GoalCount + + // skill ID list ; separated + buf.WriteLengthString(m_task_data[task_id]->activity_information[activity_id].skill_list); + + // spelll ID list ; separated -- unsure wtf we're doing here + buf.WriteLengthString(m_task_data[task_id]->activity_information[activity_id].spell_list); + + buf.WriteString(m_task_data[task_id]->activity_information[activity_id].zones); + buf.WriteUInt32(0); // unknown7 + + buf.WriteString(m_task_data[task_id]->activity_information[activity_id].description_override); // description override + + if (m_task_data[task_id]->activity_information[activity_id].activity_type != ActivityGiveCash) { + buf.WriteUInt32( + client->GetTaskActivityDoneCount( + m_task_data[task_id]->type, + client_task_index, + activity_id + )); // done_count + } + else { + // For internal activity_information types, done_count is either 1 if the activity_information is complete, 0 otherwise. + buf.WriteUInt32((client->GetTaskActivityDoneCount(m_task_data[task_id]->type, client_task_index, activity_id) >= + m_task_data[task_id]->activity_information[activity_id].goal_count)); + } + + buf.WriteUInt8(1); // unknown9 + + buf.WriteString(m_task_data[task_id]->activity_information[activity_id].zones); + + auto outapp = new EQApplicationPacket(OP_TaskActivity, buf); + + client->QueuePacket(outapp); + safe_delete(outapp); + +} + +void TaskManager::SendActiveTasksToClient(Client *client, bool task_complete) +{ + auto state = client->GetTaskState(); + if (!state) { + return; + } + + for (int task_index = 0; task_index < MAXACTIVEQUESTS + 1; task_index++) { + int task_id = state->m_active_tasks[task_index].task_id; + if ((task_id == 0) || (m_task_data[task_id] == 0)) { + continue; + } + int start_time = state->m_active_tasks[task_index].accepted_time; + + SendActiveTaskDescription( + client, task_id, state->m_active_tasks[task_index], start_time, m_task_data[task_id]->duration, + false + ); + LogTasks("[SendActiveTasksToClient] task_id [{}] activity_count [{}]", task_id, GetActivityCount(task_id)); + + int sequence = 0; + int fixed_index = m_task_data[task_id]->type == TaskType::Task ? 0 : task_index - 1; // hmmm fuck + for (int activity_id = 0; activity_id < GetActivityCount(task_id); activity_id++) { + if (client->GetTaskActivityState(m_task_data[task_id]->type, fixed_index, activity_id) != ActivityHidden) { + LogTasks( + "[SendActiveTasksToClient] (Long Update) task_id [{}] activity_id [{}] fixed_index [{}] task_complete [{}]", + task_id, + activity_id, + fixed_index, + task_complete ? "true" : "false" + ); + + if (activity_id == GetActivityCount(task_id) - 1) { + SendTaskActivityLong( + client, + task_id, + activity_id, + fixed_index, + m_task_data[task_id]->activity_information[activity_id].optional, + task_complete + ); + } + else { + SendTaskActivityLong( + client, + task_id, + activity_id, + fixed_index, + m_task_data[task_id]->activity_information[activity_id].optional, + 0 + ); + } + } + else { + LogTasks( + "[SendActiveTasksToClient] (Short Update) task_id [{}] activity_id [{}] fixed_index [{}]", + task_id, + activity_id, + fixed_index + ); + + SendTaskActivityShort(client, task_id, activity_id, fixed_index); + } + sequence++; + } + } +} + +void TaskManager::SendSingleActiveTaskToClient( + Client *client, ClientTaskInformation &task_info, bool task_complete, + bool bring_up_task_journal +) +{ + int task_id = task_info.task_id; + if (task_id == 0 || m_task_data[task_id] == nullptr) { + return; + } + + int start_time = task_info.accepted_time; + SendActiveTaskDescription( + client, + task_id, + task_info, + start_time, + m_task_data[task_id]->duration, + bring_up_task_journal + ); + Log(Logs::General, + Logs::Tasks, + "[UPDATE] SendSingleActiveTasksToClient: Task %i, Activities: %i", + task_id, + GetActivityCount(task_id)); + + for (int activity_id = 0; activity_id < GetActivityCount(task_id); activity_id++) { + if (task_info.activity[activity_id].activity_state != ActivityHidden) { + LogTasks("[SendSingleActiveTaskToClient] Long [{}] [{}] complete [{}]", + task_id, + activity_id, + task_complete); + if (activity_id == GetActivityCount(task_id) - 1) { + SendTaskActivityLong( + client, task_id, activity_id, task_info.slot, + m_task_data[task_id]->activity_information[activity_id].optional, task_complete + ); + } + else { + SendTaskActivityLong( + client, task_id, activity_id, task_info.slot, + m_task_data[task_id]->activity_information[activity_id].optional, 0 + ); + } + } + else { + LogTasks("[SendSingleActiveTaskToClient] Short [{}] [{}]", task_id, activity_id); + SendTaskActivityShort(client, task_id, activity_id, task_info.slot); + } + } +} + +void TaskManager::SendActiveTaskDescription( + Client *client, + int task_id, + ClientTaskInformation &task_info, + int start_time, + int duration, + bool bring_up_task_journal +) +{ + if ((task_id < 1) || (task_id >= MAXTASKS) || !m_task_data[task_id]) { + return; + } + + int packet_length = sizeof(TaskDescriptionHeader_Struct) + m_task_data[task_id]->title.length() + 1 + + sizeof(TaskDescriptionData1_Struct) + m_task_data[task_id]->description.length() + 1 + + sizeof(TaskDescriptionData2_Struct) + 1 + sizeof(TaskDescriptionTrailer_Struct); + + // If there is an item make the reward text into a link to the item (only the first item if a list + // is specified). I have been unable to get multiple item links to work. + // + if (m_task_data[task_id]->reward_id && m_task_data[task_id]->item_link.empty()) { + int item_id = 0; + // If the reward is a list of items, and the first entry on the list is valid + if (m_task_data[task_id]->reward_method == METHODSINGLEID) { + item_id = m_task_data[task_id]->reward_id; + } + else if (m_task_data[task_id]->reward_method == METHODLIST) { + item_id = m_goal_list_manager.GetFirstEntry(m_task_data[task_id]->reward_id); + if (item_id < 0) { + item_id = 0; + } + } + + if (item_id) { + const EQ::ItemData *reward_item = database.GetItem(item_id); + + EQ::SayLinkEngine linker; + linker.SetLinkType(EQ::saylink::SayLinkItemData); + linker.SetItemData(reward_item); + linker.SetTaskUse(); + m_task_data[task_id]->item_link = linker.GenerateLink(); + } + } + + packet_length += m_task_data[task_id]->reward.length() + 1 + m_task_data[task_id]->item_link.length() + 1; + + char *Ptr; + TaskDescriptionHeader_Struct *task_description_header; + TaskDescriptionData1_Struct *tdd1; + TaskDescriptionData2_Struct *tdd2; + TaskDescriptionTrailer_Struct *tdt; + + auto outapp = new EQApplicationPacket(OP_TaskDescription, packet_length); + + task_description_header = (TaskDescriptionHeader_Struct *) outapp->pBuffer; + + task_description_header->SequenceNumber = task_info.slot; + task_description_header->TaskID = task_id; + task_description_header->open_window = bring_up_task_journal; + task_description_header->task_type = static_cast(m_task_data[task_id]->type); + task_description_header->reward_type = 0; // TODO: 4 says Radiant Crystals else Ebon Crystals when shared task + + Ptr = (char *) task_description_header + sizeof(TaskDescriptionHeader_Struct); + + sprintf(Ptr, "%s", m_task_data[task_id]->title.c_str()); + Ptr += m_task_data[task_id]->title.length() + 1; + + tdd1 = (TaskDescriptionData1_Struct *) Ptr; + + tdd1->Duration = duration; + tdd1->dur_code = static_cast(m_task_data[task_id]->duration_code); + + tdd1->StartTime = start_time; + + Ptr = (char *) tdd1 + sizeof(TaskDescriptionData1_Struct); + + sprintf(Ptr, "%s", m_task_data[task_id]->description.c_str()); + Ptr += m_task_data[task_id]->description.length() + 1; + + tdd2 = (TaskDescriptionData2_Struct *) Ptr; + + // we have this reward stuff! + // if we ever don't hardcode this, TaskDescriptionTrailer_Struct will need to be fixed since + // "has_reward_selection" is after this bool! Smaller packet when this is 0 + tdd2->has_rewards = 1; + + tdd2->coin_reward = m_task_data[task_id]->cash_reward; + tdd2->xp_reward = m_task_data[task_id]->experience_reward ? 1 : 0; // just booled + tdd2->faction_reward = m_task_data[task_id]->faction_reward ? 1 : 0; // faction booled + + Ptr = (char *) tdd2 + sizeof(TaskDescriptionData2_Struct); + + // we actually have 2 strings here. One is max length 96 and not parsed for item links + // We actually skipped past that string incorrectly before, so TODO: fix item link string + sprintf(Ptr, "%s", m_task_data[task_id]->reward.c_str()); + Ptr += m_task_data[task_id]->reward.length() + 1; + + // second string is parsed for item links + sprintf(Ptr, "%s", m_task_data[task_id]->item_link.c_str()); + Ptr += m_task_data[task_id]->item_link.length() + 1; + + tdt = (TaskDescriptionTrailer_Struct *) Ptr; + tdt->Points = 0x00000000; // Points Count TODO: this does have a visible affect on the client ... + tdt->has_reward_selection = 0; // TODO: new rewards window + + client->QueuePacket(outapp); + safe_delete(outapp); +} + +bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_state) +{ + if (!client || !client_task_state) { + return false; + } + + int character_id = client->CharacterID(); + + client_task_state->m_active_task_count = 0; + + LogTasks("[LoadClientState] for character_id [{}]", character_id); + + auto character_tasks = CharacterTasksRepository::GetWhere( + database, + fmt::format("charid = {} ORDER BY acceptedtime", character_id) + ); + + for (auto &character_task: character_tasks) { + int task_id = character_task.taskid; + int slot = character_task.slot; + auto type = static_cast(character_task.type); + + if ((task_id < 0) || (task_id >= MAXTASKS)) { + LogTasks( + "[LoadClientState] Error: task_id [{}] out of range while loading character tasks from database", + task_id + ); + continue; + } + + // client data bucket pointer + auto task_info = client_task_state->GetClientTaskInfo(type, slot); + if (task_info == nullptr) { + LogTasks( + "[LoadClientState] Error: slot [{}] out of range while loading character tasks from database", + slot + ); + continue; + } + + if (task_info->task_id != TASKSLOTEMPTY) { + LogTasks("[LoadClientState] Error: slot [{}] for task [{}] is already occupied", slot, task_id); + continue; + } + + task_info->task_id = task_id; + task_info->current_step = -1; + task_info->accepted_time = character_task.acceptedtime; + task_info->updated = false; + + for (auto &i : task_info->activity) { + i.activity_id = -1; + } + + if (type == TaskType::Quest) { + ++client_task_state->m_active_task_count; + } + + LogTasks( + "[LoadClientState] character_id [{}] task_id [{}] accepted_time [{}]", + character_id, + task_id, + character_task.acceptedtime + ); + } + + // Load Activities + LogTasks("[LoadClientState] Loading activities for character_id [{}]", character_id); + + auto character_activities = CharacterActivitiesRepository::GetWhere( + database, + fmt::format("charid = {} ORDER BY `taskid` ASC, `activityid` ASC", character_id) + ); + + for (auto &character_activity: character_activities) { + int task_id = character_activity.taskid; + if ((task_id < 0) || (task_id >= MAXTASKS)) { + LogTasks( + "[LoadClientState] Error: task_id [{}] out of range while loading character activities from database character_id [{}]", + task_id, + character_id + ); + continue; + } + + int activity_id = character_activity.activityid; + if ((activity_id < 0) || (activity_id >= MAXACTIVITIESPERTASK)) { + LogTasks( + "[LoadClientState] Error: activity_id [{}] out of range while loading character activities from database character_id [{}]", + activity_id, + character_id + ); + + continue; + } + + ClientTaskInformation *task_info = nullptr; + if (client_task_state->m_active_task.task_id == task_id) { + task_info = &client_task_state->m_active_task; + } + + // wasn't task + if (task_info == nullptr) { + for (auto &active_quest : client_task_state->m_active_quests) { + if (active_quest.task_id == task_id) { + task_info = &active_quest; + } + } + } + + if (task_info == nullptr) { + LogTasks( + "[LoadClientState] Error: activity_id [{}] found for task_id [{}] which client does not have character_id [{}]", + activity_id, + task_id, + character_id + ); + + continue; + } + + task_info->activity[activity_id].activity_id = activity_id; + task_info->activity[activity_id].done_count = character_activity.donecount; + if (character_activity.completed) { + task_info->activity[activity_id].activity_state = ActivityCompleted; + } + else { + task_info->activity[activity_id].activity_state = ActivityHidden; + } + + task_info->activity[activity_id].updated = false; + + LogTasks( + "[LoadClientState] character_id [{}] task_id [{}] activity_id [{}] done_count [{}] completed [{}]", + character_id, + task_id, + activity_id, + character_activity.donecount, + character_activity.completed + ); + } + + if (RuleB(TaskSystem, RecordCompletedTasks)) { + CompletedTaskInformation completed_task_information{}; + + for (bool &i : completed_task_information.activity_done) { + i = false; + } + + int previous_task_id = -1; + int previous_completed_time = -1; + + auto character_completed_tasks = CompletedTasksRepository::GetWhere( + database, + fmt::format("charid = {} ORDER BY completedtime, taskid, activityid", character_id) + ); + + for (auto &character_completed_task: character_completed_tasks) { + int task_id = character_completed_task.taskid; + if ((task_id <= 0) || (task_id >= MAXTASKS)) { + LogError("[TASKS]Task ID [{}] out of range while loading completed tasks from database", task_id); + continue; + } + + // An activity_id of -1 means mark all the none optional activities in the + // task as complete. If the Rule to record optional activities is enabled, + // subsequent records for this task will flag any optional tasks that were + // completed. + int activity_id = character_completed_task.activityid; + if ((activity_id < -1) || (activity_id >= MAXACTIVITIESPERTASK)) { + LogError("[TASKS]activity_information ID [{}] out of range while loading completed tasks from database", + activity_id); + continue; + } + + int completed_time = character_completed_task.completedtime; + if ((previous_task_id != -1) && + ((task_id != previous_task_id) || (completed_time != previous_completed_time))) { + client_task_state->m_completed_tasks.push_back(completed_task_information); + for (bool &activity_done : completed_task_information.activity_done) { + activity_done = false; + } + } + + completed_task_information.task_id = previous_task_id = task_id; + completed_task_information.completed_time = previous_completed_time = completed_time; + + // If activity_id is -1, Mark all the non-optional tasks as completed. + if (activity_id < 0) { + TaskInformation *task = m_task_data[task_id]; + if (task == nullptr) { + continue; + } + + for (int i = 0; i < task->activity_count; i++) { + if (!task->activity_information[i].optional) { + completed_task_information.activity_done[i] = true; + } + } + } + else { + completed_task_information.activity_done[activity_id] = true; + } + } + + if (previous_task_id != -1) { + client_task_state->m_completed_tasks.push_back(completed_task_information); + } + + client_task_state->m_last_completed_task_loaded = client_task_state->m_completed_tasks.size(); + } + + std::string query = StringFormat( + "SELECT `taskid` FROM character_enabledtasks " + "WHERE `charid` = %i AND `taskid` >0 AND `taskid` < %i " + "ORDER BY `taskid` ASC", + character_id, MAXTASKS + ); + + auto results = database.QueryDatabase(query); + if (results.Success()) { + for (auto row = results.begin(); row != results.end(); ++row) { + int task_id = atoi(row[0]); + client_task_state->m_enabled_tasks.push_back(task_id); + LogTasksDetail("[LoadClientState] Adding task_id [{}] to enabled tasks", task_id); + } + } + + // Check that there is an entry in the client task state for every activity_information in each task + // This should only break if a ServerOP adds or deletes activites for a task that players already + // have active, or due to a bug. + for (int task_index = 0; task_index < MAXACTIVEQUESTS + 1; task_index++) { + int task_id = client_task_state->m_active_tasks[task_index].task_id; + if (task_id == TASKSLOTEMPTY) { + continue; + } + if (!m_task_data[task_id]) { + client->Message( + Chat::Red, + "Active Task Slot %i, references a task (%i), that does not exist. " + "Removing from memory. Contact a GM to resolve this.", + task_index, + task_id + ); + + LogError("[LoadClientState] Character [{}] has task [{}] which does not exist", character_id, task_id); + client_task_state->m_active_tasks[task_index].task_id = TASKSLOTEMPTY; + continue; + } + for (int activity_index = 0; activity_index < m_task_data[task_id]->activity_count; activity_index++) { + if (client_task_state->m_active_tasks[task_index].activity[activity_index].activity_id != activity_index) { + client->Message( + Chat::Red, + "Active Task %i, %s. activity_information count does not match expected value." + "Removing from memory. Contact a GM to resolve this.", + task_id, m_task_data[task_id]->title.c_str() + ); + + LogTasks( + "[LoadClientState] Fatal error in character [{}] task state. activity_information [{}] for Task [{}] either missing from client state or from task", + character_id, + activity_index, + task_id + ); + client_task_state->m_active_tasks[task_index].task_id = TASKSLOTEMPTY; + break; + } + } + } + + if (client_task_state->m_active_task.task_id != TASKSLOTEMPTY) { + client_task_state->UnlockActivities(character_id, client_task_state->m_active_task); + } + + // TODO: shared + for (auto &active_quest : client_task_state->m_active_quests) { + if (active_quest.task_id != TASKSLOTEMPTY) { + client_task_state->UnlockActivities(character_id, active_quest); + } + } + + LogTasks("[LoadClientState] for Character ID [{}] DONE!", character_id); + + return true; +} \ No newline at end of file diff --git a/zone/task_manager.h b/zone/task_manager.h new file mode 100644 index 000000000..f1fe41bd9 --- /dev/null +++ b/zone/task_manager.h @@ -0,0 +1,98 @@ +#ifndef EQEMU_TASK_MANAGER_H +#define EQEMU_TASK_MANAGER_H + +#include "tasks.h" +#include "task_client_state.h" +#include "task_proximity_manager.h" +#include "task_goal_list_manager.h" +#include "../common/types.h" +#include +#include +#include +#include + +class Client; + +class Mob; + +class TaskManager { + +public: + TaskManager(); + ~TaskManager(); + int GetActivityCount(int task_id); + bool LoadTasks(int single_task = 0); + void ReloadGoalLists(); + inline void LoadProximities(int zone_id) + { + m_proximity_manager.LoadProximities(zone_id); + } + bool LoadTaskSets(); + bool LoadClientState(Client *client, ClientTaskState *client_task_state); + bool SaveClientState(Client *client, ClientTaskState *client_task_state); + void SendTaskSelector(Client *client, Mob *mob, int task_count, int *task_list); + void SendTaskSelectorNew(Client *client, Mob *mob, int task_count, int *task_list); + bool ValidateLevel(int task_id, int player_level); + std::string GetTaskName(uint32 task_id); + TaskType GetTaskType(uint32 task_id); + void TaskSetSelector(Client *client, ClientTaskState *client_task_state, Mob *mob, int task_set_id); + // task list provided by QuestManager (perl/lua) + void TaskQuestSetSelector( + Client *client, + ClientTaskState *client_task_state, + Mob *mob, + int count, + int *tasks + ); + void SendActiveTasksToClient(Client *client, bool task_complete = false); + void SendSingleActiveTaskToClient( + Client *client, + ClientTaskInformation &task_info, + bool task_complete, + bool bring_up_task_journal = false + ); + void SendTaskActivityShort(Client *client, int task_id, int activity_id, int client_task_index); + void SendTaskActivityLong( + Client *client, + int task_id, + int activity_id, + int client_task_index, + bool optional, + bool task_complete = false + ); + void SendTaskActivityNew( + Client *client, + int task_id, + int activity_id, + int client_task_index, + bool optional, + bool task_complete = false + ); + void SendCompletedTasksToClient(Client *c, ClientTaskState *client_task_state); + void ExplainTask(Client *client, int task_id); + int FirstTaskInSet(int task_set); + int LastTaskInSet(int task_set); + int NextTaskInSet(int task_set, int task_id); + bool IsTaskRepeatable(int task_id); + + friend class ClientTaskState; + + +private: + TaskGoalListManager m_goal_list_manager; + TaskProximityManager m_proximity_manager; + TaskInformation *m_task_data[MAXTASKS]{}; + std::vector m_task_sets[MAXTASKSETS]; + void SendActiveTaskDescription( + Client *client, + int task_id, + ClientTaskInformation &task_info, + int start_time, + int duration, + bool bring_up_task_journal = false + ); + +}; + + +#endif //EQEMU_TASK_MANAGER_H diff --git a/zone/task_proximity_manager.cpp b/zone/task_proximity_manager.cpp new file mode 100644 index 000000000..ee46acbcb --- /dev/null +++ b/zone/task_proximity_manager.cpp @@ -0,0 +1,80 @@ +#include "../common/global_define.h" +#include "../common/repositories/proximities_repository.h" +#include "../common/rulesys.h" +#include "client.h" +#include "mob.h" +#include "quest_parser_collection.h" +#include "task_proximity_manager.h" +#include "tasks.h" +#include "zonedb.h" + +TaskProximityManager::TaskProximityManager() +{ + + +} + +TaskProximityManager::~TaskProximityManager() +{ + + +} + +bool TaskProximityManager::LoadProximities(int zone_id) +{ + TaskProximity proximity{}; + m_task_proximities.clear(); + + auto proximities = ProximitiesRepository::GetWhere( + content_db, + fmt::format("zoneid = {} ORDER BY `zoneid` ASC", zone_id) + ); + + for (auto &row: proximities) { + proximity.explore_id = row.exploreid; + proximity.min_x = row.minx; + proximity.max_x = row.maxx; + proximity.min_y = row.miny; + proximity.max_y = row.maxy; + proximity.min_z = row.minz; + proximity.max_z = row.maxz; + + m_task_proximities.push_back(proximity); + } + + LogTasks("Loaded [{}] Task Proximities", proximities.size()); + + return true; +} + +int TaskProximityManager::CheckProximities(float x, float y, float z) +{ + for (auto &task_proximity : m_task_proximities) { + + TaskProximity *p_proximity = &task_proximity; + + Log( + Logs::General, + Logs::Tasks, + "[Proximity] Checking %8.3f, %8.3f, %8.3f against %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f", + x, + y, + z, + p_proximity->min_x, + p_proximity->max_x, + p_proximity->min_y, + p_proximity->max_y, + p_proximity->min_z, + p_proximity->max_z + ); + + if (x < p_proximity->min_x || x > p_proximity->max_x || y < p_proximity->min_y || y > p_proximity->max_y || + z < p_proximity->min_z || z > p_proximity->max_z) { + continue; + } + + return p_proximity->explore_id; + } + + return 0; +} diff --git a/zone/task_proximity_manager.h b/zone/task_proximity_manager.h new file mode 100644 index 000000000..a3fe44c07 --- /dev/null +++ b/zone/task_proximity_manager.h @@ -0,0 +1,27 @@ +#ifndef EQEMU_TASK_PROXIMITY_MANAGER_H +#define EQEMU_TASK_PROXIMITY_MANAGER_H + +struct TaskProximity { + int explore_id; + float min_x; + float max_x; + float min_y; + float max_y; + float min_z; + float max_z; +}; + +// This class is used for managing proximities so that Quest NPC proximities don't need to be used. +class TaskProximityManager { + +public: + TaskProximityManager(); + ~TaskProximityManager(); + bool LoadProximities(int zone_id); + int CheckProximities(float x, float y, float z); + +private: + std::vector m_task_proximities; +}; + +#endif //EQEMU_TASK_PROXIMITY_MANAGER_H diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 3b8011829..4f240bab5 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -1,2483 +1,38 @@ - -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2008 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 "../common/global_define.h" -#include "tasks.h" - -#include - -#ifdef _WINDOWS -#define strcasecmp _stricmp -#endif - #include "../common/misc_functions.h" #include "../common/rulesys.h" #include "../common/string_util.h" -#include "../common/say_link.h" -#include "zonedb.h" -#include "zone_store.h" -#include "../common/repositories/goallists_repository.h" #include "client.h" -#include "entity.h" -#include "mob.h" -#include "string_ids.h" - #include "queryserv.h" #include "quest_parser_collection.h" +#include "tasks.h" +#include "zonedb.h" -extern QueryServ* QServ; +extern QueryServ *QServ; -TaskManager::TaskManager() { - for(int i=0; i 0 AND `id` < %i " - "AND `taskid` >= 0 AND `taskid` < %i " - "ORDER BY `id`, `taskid` ASC", - MAXTASKSETS, MAXTASKS - ); - auto results = content_db.QueryDatabase(query); - if (!results.Success()) { - LogError("Error in TaskManager::LoadTaskSets: [{}]", results.ErrorMessage().c_str()); - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - int taskSet = atoi(row[0]); - int taskID = atoi(row[1]); - - TaskSets[taskSet].push_back(taskID); - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] Adding TaskID %4i to TaskSet %4i", taskID, taskSet); - } - - return true; -} - -bool TaskManager::LoadSingleTask(int TaskID) { - - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] TaskManager::LoadSingleTask(%i)", TaskID); - - if((TaskID <= 0) || (TaskID >= MAXTASKS)) return false; - - // If this task already exists in memory, free all the dynamically allocated strings. - if(Tasks[TaskID]) { - safe_delete(Tasks[TaskID]); - } - - return LoadTasks(TaskID); -} - -void TaskManager::ReloadGoalLists() { - - if(!GoalListManager.LoadLists()) - Log(Logs::Detail, Logs::Tasks,"TaskManager::LoadTasks LoadLists failed"); -} - -bool TaskManager::LoadTasks(int singleTask) -{ - // If TaskID !=0, then just load the task specified. - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] TaskManager::LoadTasks Called"); - - std::string query; - if (singleTask == 0) { - if (!GoalListManager.LoadLists()) - Log(Logs::Detail, Logs::Tasks, "TaskManager::LoadTasks LoadLists failed"); - - if (!LoadTaskSets()) - Log(Logs::Detail, Logs::Tasks, "TaskManager::LoadTasks LoadTaskSets failed"); - - query = StringFormat("SELECT `id`, `type`, `duration`, `duration_code`, `title`, `description`, " - "`reward`, `rewardid`, `cashreward`, `xpreward`, `rewardmethod`, `faction_reward`," - "`minlevel`, `maxlevel`, `repeatable`, `completion_emote` FROM `tasks` WHERE `id` < %i", - MAXTASKS); - } else - query = StringFormat("SELECT `id`, `type`, `duration`, `duration_code`, `title`, `description`, " - "`reward`, `rewardid`, `cashreward`, `xpreward`, `rewardmethod`, `faction_reward`," - "`minlevel`, `maxlevel`, `repeatable`, `completion_emote` FROM `tasks` WHERE `id` = %i", - singleTask); - - const char *ERR_MYSQLERROR = "[TASKS]Error in TaskManager::LoadTasks: %s"; - - auto results = content_db.QueryDatabase(query); - if (!results.Success()) { - LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str()); - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - int taskID = atoi(row[0]); - - if ((taskID <= 0) || (taskID >= MAXTASKS)) { - // This shouldn't happen, as the SELECT is bounded by MAXTASKS - LogError("[TASKS]Task ID [{}] out of range while loading tasks from database", taskID); - continue; + if (RuleB(TaskSystem, EnableTaskSystem) && task_manager) { + if (task_state) { + safe_delete(task_state); } - Tasks[taskID] = new TaskInformation; - Tasks[taskID]->type = static_cast(atoi(row[1])); - Tasks[taskID]->Duration = atoi(row[2]); - Tasks[taskID]->dur_code = static_cast(atoi(row[3])); - Tasks[taskID]->Title = row[4]; - Tasks[taskID]->Description = row[5]; - Tasks[taskID]->Reward = row[6]; - Tasks[taskID]->RewardID = atoi(row[7]); - Tasks[taskID]->CashReward = atoi(row[8]); - Tasks[taskID]->XPReward = atoi(row[9]); - Tasks[taskID]->RewardMethod = (TaskMethodType)atoi(row[10]); - Tasks[taskID]->faction_reward = atoi(row[11]); - Tasks[taskID]->MinLevel = atoi(row[12]); - Tasks[taskID]->MaxLevel = atoi(row[13]); - Tasks[taskID]->Repeatable = atoi(row[14]); - Tasks[taskID]->completion_emote = row[15]; - Tasks[taskID]->ActivityCount = 0; - Tasks[taskID]->SequenceMode = ActivitiesSequential; - Tasks[taskID]->LastStep = 0; - - Log(Logs::General, Logs::Tasks, - "[GLOBALLOAD] TaskID: %5i, Duration: %8i, Reward: %s MinLevel %i MaxLevel %i " - "Repeatable: %s", - taskID, Tasks[taskID]->Duration, Tasks[taskID]->Reward.c_str(), - Tasks[taskID]->MinLevel, Tasks[taskID]->MaxLevel, Tasks[taskID]->Repeatable ? "Yes" : "No"); - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] Title: %s", Tasks[taskID]->Title.c_str()); - } - - if (singleTask == 0) - query = - StringFormat("SELECT `taskid`, `step`, `activityid`, `activitytype`, `target_name`, `item_list`, " - "`skill_list`, `spell_list`, `description_override`, `goalid`, `goalmethod`, " - "`goalcount`, `delivertonpc`, `zones`, `optional` FROM `task_activities` WHERE `taskid` < " - "%i AND `activityid` < %i ORDER BY taskid, activityid ASC", - MAXTASKS, MAXACTIVITIESPERTASK); - else - query = - StringFormat("SELECT `taskid`, `step`, `activityid`, `activitytype`, `target_name`, `item_list`, " - "`skill_list`, `spell_list`, `description_override`, `goalid`, `goalmethod`, " - "`goalcount`, `delivertonpc`, `zones`, `optional` FROM `task_activities` WHERE `taskid` = " - "%i AND `activityid` < %i ORDER BY taskid, activityid ASC", - singleTask, MAXACTIVITIESPERTASK); - results = content_db.QueryDatabase(query); - if (!results.Success()) { - LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str()); - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - int taskID = atoi(row[0]); - int step = atoi(row[1]); - - int activityID = atoi(row[2]); - - if ((taskID <= 0) || (taskID >= MAXTASKS) || (activityID < 0) || (activityID >= MAXACTIVITIESPERTASK)) { - // This shouldn't happen, as the SELECT is bounded by MAXTASKS - LogError("[TASKS]Task or Activity ID ([{}], [{}]) out of range while loading activities from database", taskID, activityID); - continue; - } - - if (Tasks[taskID] == nullptr) { - LogError("[TASKS]Activity for non-existent task ([{}], [{}]) while loading activities from database", - taskID, activityID); - continue; - } - - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].StepNumber = step; - - if (step != 0) - Tasks[taskID]->SequenceMode = ActivitiesStepped; - - if (step > Tasks[taskID]->LastStep) - Tasks[taskID]->LastStep = step; - - // Task Activities MUST be numbered sequentially from 0. If not, log an error - // and set the task to nullptr. Subsequent activities for this task will raise - // ERR_NOTASK errors. - // Change to (activityID != (Tasks[taskID]->ActivityCount + 1)) to index from 1 - if (activityID != Tasks[taskID]->ActivityCount) { - LogError("[TASKS]Activities for Task [{}] are not sequential starting at 0. Not loading task", taskID, - activityID); - Tasks[taskID] = nullptr; - continue; - } - - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Type = atoi(row[3]); - - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].target_name = row[4]; - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].item_list = row[5]; - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].skill_list = row[6]; - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].skill_id = atoi(row[6]); // for older clients - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].spell_list = row[7]; - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].spell_id = atoi(row[7]); // for older clients - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].desc_override = row[8]; - - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalID = atoi(row[9]); - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalMethod = (TaskMethodType)atoi(row[10]); - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalCount = atoi(row[11]); - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].DeliverToNPC = atoi(row[12]); - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].zones = row[13]; - auto zones = SplitString(Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].zones, ';'); - for (auto && e : zones) - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].ZoneIDs.push_back(std::stoi(e)); - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Optional = atoi(row[14]); - - Log(Logs::General, Logs::Tasks, - "[GLOBALLOAD] Activity Slot %2i: ID %i for Task %5i. Type: %3i, GoalID: %8i, " - "GoalMethod: %i, GoalCount: %3i, Zones:%s", - Tasks[taskID]->ActivityCount, activityID, taskID, - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Type, - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalID, - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalMethod, - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalCount, - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].zones.c_str()); - - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] target_name: %s", - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].target_name.c_str()); - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] item_list: %s", - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].item_list.c_str()); - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] skill_list: %s", - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].skill_list.c_str()); - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] spell_list: %s", - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].spell_list.c_str()); - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] description_override: %s", - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].desc_override.c_str()); - - Tasks[taskID]->ActivityCount++; - } - - return true; -} - -bool TaskManager::SaveClientState(Client *c, ClientTaskState *state) -{ - // I am saving the slot in the ActiveTasks table, because unless a Task is cancelled/completed, the client - // doesn't seem to like tasks moving slots between zoning and you can end up with 'bogus' activities if the task - // previously in that slot had more activities than the one now occupying it. Hopefully retaining the slot - // number for the duration of a session will overcome this. - if (!c || !state) - return false; - - const char *ERR_MYSQLERROR = "[TASKS]Error in TaskManager::SaveClientState %s"; - - int characterID = c->CharacterID(); - - Log(Logs::Detail, Logs::Tasks, "TaskManager::SaveClientState for character ID %d", characterID); - - if (state->ActiveTaskCount > 0 || state->ActiveTask.TaskID != TASKSLOTEMPTY) { // TODO: tasks - for (int task = 0; task < MAXACTIVEQUESTS + 1; task++) { - int taskID = state->ActiveTasks[task].TaskID; - if (taskID == TASKSLOTEMPTY) - continue; - - int slot = state->ActiveTasks[task].slot; - - if (state->ActiveTasks[task].Updated) { - - Log(Logs::General, Logs::Tasks, - "[CLIENTSAVE] TaskManager::SaveClientState for character ID %d, Updating TaskIndex " - "%i TaskID %i", - characterID, slot, taskID); - - std::string query = StringFormat( - "REPLACE INTO character_tasks (charid, taskid, slot, type, acceptedtime) " - "VALUES (%i, %i, %i, %i, %i)", - characterID, taskID, slot, static_cast(Tasks[taskID]->type), - state->ActiveTasks[task].AcceptedTime); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str()); - } else { - state->ActiveTasks[task].Updated = false; - } - } - - std::string query = - "REPLACE INTO character_activities (charid, taskid, activityid, donecount, completed) " - "VALUES "; - - int updatedActivityCount = 0; - for (int activityIndex = 0; activityIndex < Tasks[taskID]->ActivityCount; ++activityIndex) { - - if (!state->ActiveTasks[task].Activity[activityIndex].Updated) - continue; - - Log(Logs::General, Logs::Tasks, - "[CLIENTSAVE] TaskManager::SaveClientSate for character ID %d, Updating Activity " - "%i, %i", - characterID, slot, activityIndex); - - if (updatedActivityCount == 0) - query += - StringFormat("(%i, %i, %i, %i, %i)", characterID, taskID, activityIndex, - state->ActiveTasks[task].Activity[activityIndex].DoneCount, - state->ActiveTasks[task].Activity[activityIndex].State == - ActivityCompleted); - else - query += - StringFormat(", (%i, %i, %i, %i, %i)", characterID, taskID, activityIndex, - state->ActiveTasks[task].Activity[activityIndex].DoneCount, - state->ActiveTasks[task].Activity[activityIndex].State == - ActivityCompleted); - - updatedActivityCount++; - } - - if (updatedActivityCount == 0) - continue; - - Log(Logs::General, Logs::Tasks, "[CLIENTSAVE] Executing query %s", query.c_str()); - auto results = database.QueryDatabase(query); - - if (!results.Success()) { - LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str()); - continue; - } - - state->ActiveTasks[task].Updated = false; - for (int activityIndex = 0; activityIndex < Tasks[taskID]->ActivityCount; ++activityIndex) - state->ActiveTasks[task].Activity[activityIndex].Updated = false; - } - } - - if (!RuleB(TaskSystem, RecordCompletedTasks) || - (state->CompletedTasks.size() <= (unsigned int)state->LastCompletedTaskLoaded)) { - state->LastCompletedTaskLoaded = state->CompletedTasks.size(); - return true; - } - - const char *completedTaskQuery = "REPLACE INTO completed_tasks (charid, completedtime, taskid, activityid) " - "VALUES (%i, %i, %i, %i)"; - - for (unsigned int i = state->LastCompletedTaskLoaded; i < state->CompletedTasks.size(); i++) { - - Log(Logs::General, Logs::Tasks, - "[CLIENTSAVE] TaskManager::SaveClientState Saving Completed Task at slot %i", i); - int taskID = state->CompletedTasks[i].TaskID; - - if ((taskID <= 0) || (taskID >= MAXTASKS) || (Tasks[taskID] == nullptr)) - continue; - - // First we save a record with an ActivityID of -1. - // This indicates this task was completed at the given time. We infer that all - // none optional activities were completed. - // - std::string query = - StringFormat(completedTaskQuery, characterID, state->CompletedTasks[i].CompletedTime, taskID, -1); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str()); - continue; - } - - // If the Rule to record non-optional task completion is not enabled, don't save it - if (!RuleB(TaskSystem, RecordCompletedOptionalActivities)) - continue; - - // Insert one record for each completed optional task. - - for (int j = 0; j < Tasks[taskID]->ActivityCount; j++) { - if (!Tasks[taskID]->Activity[j].Optional || !state->CompletedTasks[i].ActivityDone[j]) - continue; - - query = StringFormat(completedTaskQuery, characterID, state->CompletedTasks[i].CompletedTime, - taskID, j); - results = database.QueryDatabase(query); - if (!results.Success()) - LogError(ERR_MYSQLERROR, results.ErrorMessage().c_str()); - } - } - - state->LastCompletedTaskLoaded = state->CompletedTasks.size(); - return true; -} - -void Client::LoadClientTaskState() { - - if(RuleB(TaskSystem, EnableTaskSystem) && taskmanager) { - if(taskstate) - safe_delete(taskstate); - - taskstate = new ClientTaskState; - if(!taskmanager->LoadClientState(this, taskstate)) { - safe_delete(taskstate); + task_state = new ClientTaskState; + if (!task_manager->LoadClientState(this, task_state)) { + safe_delete(task_state); } else { - taskmanager->SendActiveTasksToClient(this); - taskmanager->SendCompletedTasksToClient(this, taskstate); + task_manager->SendActiveTasksToClient(this); + task_manager->SendCompletedTasksToClient(this, task_state); } } - } -void Client::RemoveClientTaskState() { - - if(taskstate) { - taskstate->CancelAllTasks(this); - safe_delete(taskstate); - } -} - -bool TaskManager::LoadClientState(Client *c, ClientTaskState *state) +void Client::RemoveClientTaskState() { - if (!c || !state) - return false; - - int characterID = c->CharacterID(); - - state->ActiveTaskCount = 0; - - Log(Logs::General, Logs::Tasks, "[CLIENTLOAD] TaskManager::LoadClientState for character ID %d", characterID); - - std::string query = StringFormat("SELECT `taskid`, `slot`,`type`, `acceptedtime` " - "FROM `character_tasks` " - "WHERE `charid` = %i ORDER BY acceptedtime", - characterID); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - LogError("[TASKS]Error in TaskManager::LoadClientState load Tasks: [{}]", - results.ErrorMessage().c_str()); - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - int taskID = atoi(row[0]); - int slot = atoi(row[1]); - TaskType type = static_cast(atoi(row[2])); - - if ((taskID < 0) || (taskID >= MAXTASKS)) { - LogError("[TASKS]Task ID [{}] out of range while loading character tasks from database", taskID); - continue; - } - - auto task_info = state->GetClientTaskInfo(type, slot); - - if (task_info == nullptr) { - LogError("[TASKS] Slot [{}] out of range while loading character tasks from database", slot); - continue; - } - - if (task_info->TaskID != TASKSLOTEMPTY) { - LogError("[TASKS] Slot [{}] for Task [{}]s is already occupied", slot, - taskID); - continue; - } - - int acceptedtime = atoi(row[3]); - - task_info->TaskID = taskID; - task_info->CurrentStep = -1; - task_info->AcceptedTime = acceptedtime; - task_info->Updated = false; - - for (int i = 0; i < MAXACTIVITIESPERTASK; i++) - task_info->Activity[i].ActivityID = -1; - - if (type == TaskType::Quest) - ++state->ActiveTaskCount; - - Log(Logs::General, Logs::Tasks, - "[CLIENTLOAD] TaskManager::LoadClientState. Char: %i Task ID %i, Accepted Time: %8X", characterID, - taskID, acceptedtime); - } - - // Load Activities - Log(Logs::General, Logs::Tasks, "[CLIENTLOAD] LoadClientState. Loading activities for character ID %d", - characterID); - - query = StringFormat("SELECT `taskid`, `activityid`, `donecount`, `completed` " - "FROM `character_activities` " - "WHERE `charid` = %i " - "ORDER BY `taskid` ASC, `activityid` ASC", - characterID); - results = database.QueryDatabase(query); - if (!results.Success()) { - LogError("[TASKS]Error in TaskManager::LoadClientState load Activities: [{}]", - results.ErrorMessage().c_str()); - return false; - } - - for (auto row = results.begin(); row != results.end(); ++row) { - int taskID = atoi(row[0]); - if ((taskID < 0) || (taskID >= MAXTASKS)) { - LogError("[TASKS]Task ID [{}] out of range while loading character activities from database", taskID); - continue; - } - - int activityID = atoi(row[1]); - if ((activityID < 0) || (activityID >= MAXACTIVITIESPERTASK)) { - LogError("[TASKS]Activity ID [{}] out of range while loading character activities from database", - activityID); - continue; - } - - ClientTaskInformation *task_info = nullptr; - - if (state->ActiveTask.TaskID == taskID) - task_info = &state->ActiveTask; - - // wasn't task - if (task_info == nullptr) - for (int i = 0; i < MAXACTIVEQUESTS; i++) - if (state->ActiveQuests[i].TaskID == taskID) - task_info = &state->ActiveQuests[i]; - - if (task_info == nullptr) { - LogError("[TASKS]Activity [{}] found for task [{}] which client does not have", activityID, taskID); - continue; - } - - int doneCount = atoi(row[2]); - bool completed = atoi(row[3]); - task_info->Activity[activityID].ActivityID = activityID; - task_info->Activity[activityID].DoneCount = doneCount; - if (completed) - task_info->Activity[activityID].State = ActivityCompleted; - else - task_info->Activity[activityID].State = ActivityHidden; - - task_info->Activity[activityID].Updated = false; - - Log(Logs::General, Logs::Tasks, - "[CLIENTLOAD] TaskManager::LoadClientState. Char: %i Task ID %i, ActivityID: %i, DoneCount: %i, " - "Completed: %i", - characterID, taskID, activityID, doneCount, completed); - } - - if (RuleB(TaskSystem, RecordCompletedTasks)) { - query = StringFormat("SELECT `taskid`, `activityid`, `completedtime` " - "FROM `completed_tasks` " - "WHERE `charid` = %i ORDER BY completedtime, taskid, activityid", - characterID); - results = database.QueryDatabase(query); - if (!results.Success()) { - LogError("[TASKS]Error in TaskManager::LoadClientState load completed tasks: [{}]", - results.ErrorMessage().c_str()); - return false; - } - - CompletedTaskInformation cti; - - for (int i = 0; i < MAXACTIVITIESPERTASK; i++) - cti.ActivityDone[i] = false; - - int previousTaskID = -1; - int previousCompletedTime = -1; - - for (auto row = results.begin(); row != results.end(); ++row) { - - int taskID = atoi(row[0]); - if ((taskID <= 0) || (taskID >= MAXTASKS)) { - LogError("[TASKS]Task ID [{}] out of range while loading completed tasks from database", - taskID); - continue; - } - - // An ActivityID of -1 means mark all the none optional activities in the - // task as complete. If the Rule to record optional activities is enabled, - // subsequent records for this task will flag any optional tasks that were - // completed. - int activityID = atoi(row[1]); - if ((activityID < -1) || (activityID >= MAXACTIVITIESPERTASK)) { - LogError("[TASKS]Activity ID [{}] out of range while loading completed tasks from database", - activityID); - continue; - } - - int completedTime = atoi(row[2]); - if ((previousTaskID != -1) && - ((taskID != previousTaskID) || (completedTime != previousCompletedTime))) { - state->CompletedTasks.push_back(cti); - for (int i = 0; i < MAXACTIVITIESPERTASK; i++) - cti.ActivityDone[i] = false; - } - - cti.TaskID = previousTaskID = taskID; - cti.CompletedTime = previousCompletedTime = completedTime; - - // If ActivityID is -1, Mark all the non-optional tasks as completed. - if (activityID < 0) { - TaskInformation *task = Tasks[taskID]; - if (task == nullptr) - continue; - - for (int i = 0; i < task->ActivityCount; i++) - if (!task->Activity[i].Optional) - cti.ActivityDone[i] = true; - } else - cti.ActivityDone[activityID] = true; - } - - if (previousTaskID != -1) - state->CompletedTasks.push_back(cti); - - state->LastCompletedTaskLoaded = state->CompletedTasks.size(); - } - - query = StringFormat("SELECT `taskid` FROM character_enabledtasks " - "WHERE `charid` = %i AND `taskid` >0 AND `taskid` < %i " - "ORDER BY `taskid` ASC", - characterID, MAXTASKS); - results = database.QueryDatabase(query); - if (!results.Success()) { - LogError("[TASKS]Error in TaskManager::LoadClientState load enabled tasks: [{}]", - results.ErrorMessage().c_str()); - } else { - for (auto row = results.begin(); row != results.end(); ++row) { - int taskID = atoi(row[0]); - state->EnabledTasks.push_back(taskID); - Log(Logs::General, Logs::Tasks, "[CLIENTLOAD] Adding TaskID %i to enabled tasks", taskID); - } - } - - // Check that there is an entry in the client task state for every activity in each task - // This should only break if a ServerOP adds or deletes activites for a task that players already - // have active, or due to a bug. - for (int i = 0; i < MAXACTIVEQUESTS + 1; i++) { - int taskID = state->ActiveTasks[i].TaskID; - if (taskID == TASKSLOTEMPTY) - continue; - if (!Tasks[taskID]) { - c->Message(Chat::Red, - "Active Task Slot %i, references a task (%i), that does not exist. " - "Removing from memory. Contact a GM to resolve this.", - i, taskID); - - LogError("[TASKS]Character [{}] has task [{}] which does not exist", - characterID, taskID); - state->ActiveTasks[i].TaskID = TASKSLOTEMPTY; - continue; - } - for (int j = 0; j < Tasks[taskID]->ActivityCount; j++) { - - if (state->ActiveTasks[i].Activity[j].ActivityID != j) { - c->Message(Chat::Red, - "Active Task %i, %s. Activity count does not match expected value." - "Removing from memory. Contact a GM to resolve this.", - taskID, Tasks[taskID]->Title.c_str()); - - LogError("[TASKS]Fatal error in character [{}] task state. Activity [{}] for Task [{}] either missing from client state or from task", - characterID, j, taskID); - state->ActiveTasks[i].TaskID = TASKSLOTEMPTY; - break; - } - } - } - - if (state->ActiveTask.TaskID != TASKSLOTEMPTY) - state->UnlockActivities(characterID, state->ActiveTask); - // TODO: shared - for (int i = 0; i < MAXACTIVEQUESTS; i++) - if (state->ActiveQuests[i].TaskID != TASKSLOTEMPTY) - state->UnlockActivities(characterID, state->ActiveQuests[i]); - - Log(Logs::General, Logs::Tasks, "[CLIENTLOAD] LoadClientState for Character ID %d DONE!", characterID); - return true; -} - -void ClientTaskState::EnableTask(int characterID, int taskCount, int *tasks) { - - // Check if the Task is already enabled for this client - // - std::vector tasksEnabled; - - for(int i=0; i tasks[i]) - break; - ++iterator; - } - - if(addTask) { - EnabledTasks.insert(iterator, tasks[i]); - // Make a note of the task we enabled, for later SQL generation - tasksEnabled.push_back(tasks[i]); - } - } - - Log(Logs::General, Logs::Tasks, "[UPDATE] New enabled task list "); - for(unsigned int i=0; i tasksDisabled; - - for(int i=0; i taskList[i]) - break; - - ++iterator; - } - - if(removeTask) { - EnabledTasks.erase(iterator); - tasksDisabled.push_back(taskList[i]); - } - } - - Log(Logs::General, Logs::Tasks, "[UPDATE] New enabled task list "); - for(unsigned int i=0; i::iterator Iterator; - - Iterator = EnabledTasks.begin(); - - while(Iterator != EnabledTasks.end()) { - if((*Iterator) == TaskID) return true; - if((*Iterator) > TaskID) break; - ++Iterator; - } - - return false; -} - -int ClientTaskState::EnabledTaskCount(int TaskSetID) { - - // Return the number of tasks in TaskSet that this character is enabled for. - - unsigned int EnabledTaskIndex = 0; - unsigned int TaskSetIndex = 0; - int EnabledTaskCount = 0; - - if((TaskSetID<=0) || (TaskSetID>=MAXTASKSETS)) return -1; - - while((EnabledTaskIndex < EnabledTasks.size()) && (TaskSetIndex < taskmanager->TaskSets[TaskSetID].size())) { - - if(EnabledTasks[EnabledTaskIndex] == taskmanager->TaskSets[TaskSetID][TaskSetIndex]) { - - EnabledTaskCount++; - EnabledTaskIndex++; - TaskSetIndex++; - continue; - } - - if(EnabledTasks[EnabledTaskIndex] < taskmanager->TaskSets[TaskSetID][TaskSetIndex]) - EnabledTaskIndex++; - else - TaskSetIndex++; - - } - - return EnabledTaskCount; -} -int ClientTaskState::ActiveTasksInSet(int TaskSetID) { - - - if((TaskSetID<=0) || (TaskSetID>=MAXTASKSETS)) return -1; - - int Count = 0; - - for(unsigned int i=0; iTaskSets[TaskSetID].size(); i++) - if(IsTaskActive(taskmanager->TaskSets[TaskSetID][i])) - Count++; - - return Count; -} - -int ClientTaskState::CompletedTasksInSet(int TaskSetID) { - - - if((TaskSetID<=0) || (TaskSetID>=MAXTASKSETS)) return -1; - - int Count = 0; - - for(unsigned int i=0; iTaskSets[TaskSetID].size(); i++) - if(IsTaskCompleted(taskmanager->TaskSets[TaskSetID][i])) - Count++; - - return Count; -} - -bool ClientTaskState::HasSlotForTask(TaskInformation *task) -{ - if (task == nullptr) - return false; - - switch (task->type) { - case TaskType::Task: - return ActiveTask.TaskID == TASKSLOTEMPTY; - case TaskType::Shared: - return false; // todo - case TaskType::Quest: - for (int i = 0; i < MAXACTIVEQUESTS; ++i) - if (ActiveQuests[i].TaskID == TASKSLOTEMPTY) - return true; - case TaskType::E: - return false; // removed on live - } - - return false; -} - -int TaskManager::FirstTaskInSet(int TaskSetID) { - - if((TaskSetID<=0) || (TaskSetID>=MAXTASKSETS)) return 0; - - if(TaskSets[TaskSetID].empty()) return 0; - - auto Iterator = TaskSets[TaskSetID].begin(); - - while(Iterator != TaskSets[TaskSetID].end()) { - if((*Iterator) > 0) - return (*Iterator); - ++Iterator; - } - - return 0; -} - -int TaskManager::LastTaskInSet(int TaskSetID) { - - if((TaskSetID<=0) || (TaskSetID>=MAXTASKSETS)) return 0; - - if(TaskSets[TaskSetID].empty()) return 0; - - return TaskSets[TaskSetID][TaskSets[TaskSetID].size()-1]; -} - -int TaskManager::NextTaskInSet(int TaskSetID, int TaskID) { - - if((TaskSetID<=0) || (TaskSetID>=MAXTASKSETS)) return 0; - - if(TaskSets[TaskSetID].empty()) return 0; - - for(unsigned int i=0; i TaskID) return TaskSets[TaskSetID][i]; - } - - return 0; -} - -bool TaskManager::AppropriateLevel(int TaskID, int PlayerLevel) { - - if(Tasks[TaskID] == nullptr) return false; - - if(Tasks[TaskID]->MinLevel && (PlayerLevel < Tasks[TaskID]->MinLevel)) return false; - - if(Tasks[TaskID]->MaxLevel && (PlayerLevel > Tasks[TaskID]->MaxLevel)) return false; - - return true; - -} - -std::string TaskManager::GetTaskName(uint32 task_id) -{ - if (task_id > 0 && task_id < MAXTASKS) { - if (Tasks[task_id] != nullptr) { - return Tasks[task_id]->Title; - } - } - - return std::string(); -} - -TaskType TaskManager::GetTaskType(uint32 task_id) -{ - if (task_id > 0 && task_id < MAXTASKS) { - if (Tasks[task_id] != nullptr) { - return Tasks[task_id]->type; - } - } - return TaskType::Task; -} - -int TaskManager::GetTaskMinLevel(int TaskID) -{ - if (Tasks[TaskID]->MinLevel) - { - return Tasks[TaskID]->MinLevel; - } - - return -1; -} - -int TaskManager::GetTaskMaxLevel(int TaskID) -{ - if (Tasks[TaskID]->MaxLevel) - { - return Tasks[TaskID]->MaxLevel; - } - - return -1; -} - -void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID) -{ - int TaskList[MAXCHOOSERENTRIES]; - int TaskListIndex = 0; - int PlayerLevel = c->GetLevel(); - - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSetSelector called for taskset %i. EnableTaskSize is %i", - TaskSetID, state->EnabledTasks.size()); - - if (TaskSetID <= 0 || TaskSetID >= MAXTASKSETS) - return; - - if (TaskSets[TaskSetID].empty()) { - mob->SayString(c, Chat::Yellow, MAX_ACTIVE_TASKS, c->GetName()); // I think this is suppose to be yellow - return; - } - - bool all_enabled = false; - - // A TaskID of 0 in a TaskSet indicates that all Tasks in the set are enabled for all players. - if (TaskSets[TaskSetID][0] == 0) { - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSets[%i][0] == 0. All Tasks in Set enabled.", TaskSetID); - all_enabled = true; - } - - auto Iterator = TaskSets[TaskSetID].begin(); - - if (all_enabled) - ++Iterator; // skip first when all enabled since it's useless data - - while (Iterator != TaskSets[TaskSetID].end() && TaskListIndex < MAXCHOOSERENTRIES) { - auto task = *Iterator; - // verify level, we're not currently on it, repeatable status, if it's a (shared) task - // we aren't currently on another, and if it's enabled if not all_enabled - if ((all_enabled || state->IsTaskEnabled(task)) && AppropriateLevel(task, PlayerLevel) && - !state->IsTaskActive(task) && state->HasSlotForTask(Tasks[task]) && // this slot checking is a bit silly, but we allow mixing of task types ... - (IsTaskRepeatable(task) || !state->IsTaskCompleted(task))) - TaskList[TaskListIndex++] = task; - - ++Iterator; - } - - if (TaskListIndex > 0) { - SendTaskSelector(c, mob, TaskListIndex, TaskList); - } else { - mob->SayString(c, Chat::Yellow, MAX_ACTIVE_TASKS, c->GetName()); // check color, I think this might be only for (Shared) Tasks, w/e -- think should be yellow - } - - return; -} - -// unlike the non-Quest version of this function, it does not check enabled, that is assumed the responsibility of the quest to handle -// we do however still want it to check the other stuff like level, active, room, etc -void TaskManager::TaskQuestSetSelector(Client *c, ClientTaskState *state, Mob *mob, int count, int *tasks) -{ - int TaskList[MAXCHOOSERENTRIES]; - int TaskListIndex = 0; - int PlayerLevel = c->GetLevel(); - - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskQuestSetSelector called for array size %d", count); - - if (count <= 0) - return; - - for (int i = 0; i < count; ++i) { - auto task = tasks[i]; - // verify level, we're not currently on it, repeatable status, if it's a (shared) task - // we aren't currently on another, and if it's enabled if not all_enabled - if (AppropriateLevel(task, PlayerLevel) && - !state->IsTaskActive(task) && state->HasSlotForTask(Tasks[task]) && // this slot checking is a bit silly, but we allow mixing of task types ... - (IsTaskRepeatable(task) || !state->IsTaskCompleted(task))) - TaskList[TaskListIndex++] = task; - } - - if (TaskListIndex > 0) { - SendTaskSelector(c, mob, TaskListIndex, TaskList); - } else { - mob->SayString(c, Chat::Yellow, MAX_ACTIVE_TASKS, c->GetName()); // check color, I think this might be only for (Shared) Tasks, w/e -- think should be yellow - } - - return; -} - -void TaskManager::SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *TaskList) { - - if (c->ClientVersion() >= EQ::versions::ClientVersion::RoF) - { - SendTaskSelectorNew(c, mob, TaskCount, TaskList); - return; - } - // Titanium OpCode: 0x5e7c - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSelector for %i Tasks", TaskCount); - int PlayerLevel = c->GetLevel(); - - // Check if any of the tasks exist - for (int i = 0; i < TaskCount; i++) { - if (Tasks[TaskList[i]] != nullptr) - break; - } - - int ValidTasks = 0; - - for (int i = 0; i < TaskCount; i++) { - if (!AppropriateLevel(TaskList[i], PlayerLevel)) - continue; - if (c->IsTaskActive(TaskList[i])) - continue; - if (!IsTaskRepeatable(TaskList[i]) && c->IsTaskCompleted(TaskList[i])) - continue; - - ValidTasks++; - } - - if (ValidTasks == 0) - return; - - SerializeBuffer buf(50 * ValidTasks); - - - buf.WriteUInt32(ValidTasks); - buf.WriteUInt32(2); // task type, live doesn't let you send more than one type, but we do? - buf.WriteUInt32(mob->GetID()); - - for (int i = 0; i < TaskCount; i++) { - if (!AppropriateLevel(TaskList[i], PlayerLevel)) - continue; - if (c->IsTaskActive(TaskList[i])) - continue; - if (!IsTaskRepeatable(TaskList[i]) && c->IsTaskCompleted(TaskList[i])) - continue; - - buf.WriteUInt32(TaskList[i]); // TaskID - if (c->ClientVersion() != EQ::versions::ClientVersion::Titanium) - buf.WriteFloat(1.0f); // affects color, difficulty? - buf.WriteUInt32(Tasks[TaskList[i]]->Duration); - buf.WriteUInt32(static_cast(Tasks[TaskList[i]]->dur_code)); - - buf.WriteString(Tasks[TaskList[i]]->Title); // max 64 with null - buf.WriteString(Tasks[TaskList[i]]->Description); // max 4000 with null - - if (c->ClientVersion() != EQ::versions::ClientVersion::Titanium) - buf.WriteUInt8(0); // Has reward set flag - - buf.WriteUInt32(Tasks[TaskList[i]]->ActivityCount); - - for (int j = 0; j < Tasks[TaskList[i]]->ActivityCount; ++j) { - buf.WriteUInt32(j); // ActivityNumber - auto &activity = Tasks[TaskList[i]]->Activity[j]; - buf.WriteUInt32(activity.Type); - buf.WriteUInt32(0); // solo, group, raid? - buf.WriteString(activity.target_name); // max length 64, "target name" so like loot x foo from bar (this is bar) - - buf.WriteString(activity.item_list); // max length 64 in these clients - - buf.WriteUInt32(activity.GoalCount); - - buf.WriteInt32(activity.skill_id); - buf.WriteInt32(activity.spell_id); - buf.WriteInt32(activity.ZoneIDs.empty() ? 0 : activity.ZoneIDs.front()); - buf.WriteString(activity.desc_override); - } - } - - auto outapp = new EQApplicationPacket(OP_OpenNewTasksWindow, buf); - - c->QueuePacket(outapp); - safe_delete(outapp); - -} - -void TaskManager::SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *TaskList) -{ - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSelector for %i Tasks", TaskCount); - - int PlayerLevel = c->GetLevel(); - - // Check if any of the tasks exist - for (int i = 0; i < TaskCount; i++) - if (Tasks[TaskList[i]] != nullptr) - break; - - int ValidTasks = 0; - - for (int i = 0; i < TaskCount; i++) { - if (!AppropriateLevel(TaskList[i], PlayerLevel)) - continue; - if (c->IsTaskActive(TaskList[i])) - continue; - if (!IsTaskRepeatable(TaskList[i]) && c->IsTaskCompleted(TaskList[i])) - continue; - - ValidTasks++; - } - - if (ValidTasks == 0) - return; - - SerializeBuffer buf(50 * ValidTasks); - - buf.WriteUInt32(ValidTasks); // TaskCount - buf.WriteUInt32(2); // Type, valid values: 0-3. 0 = Task, 1 = Shared Task, 2 = Quest, 3 = ??? -- should fix maybe some day, but we let more than 1 type through :P - // so I guess an NPC can only offer one type of quests or we can only open a selection with one type :P (so quest call can tell us I guess) - // this is also sent in OP_TaskDescription - buf.WriteUInt32(mob->GetID()); // TaskGiver - - for (int i = 0; i < TaskCount; i++) { // max 40 - if (!AppropriateLevel(TaskList[i], PlayerLevel)) - continue; - if (c->IsTaskActive(TaskList[i])) - continue; - if (!IsTaskRepeatable(TaskList[i]) && c->IsTaskCompleted(TaskList[i])) - continue; - - buf.WriteUInt32(TaskList[i]); // TaskID - buf.WriteFloat(1.0f); // affects color, difficulty? - buf.WriteUInt32(Tasks[TaskList[i]]->Duration); - buf.WriteUInt32(static_cast(Tasks[TaskList[i]]->dur_code)); // 1 = Short, 2 = Medium, 3 = Long, anything else Unlimited - - buf.WriteString(Tasks[TaskList[i]]->Title); // max 64 with null - buf.WriteString(Tasks[TaskList[i]]->Description); // max 4000 with null - - buf.WriteUInt8(0); // Has reward set flag - buf.WriteUInt32(Tasks[TaskList[i]]->ActivityCount); // ActivityCount - - for (int j = 0; j < Tasks[TaskList[i]]->ActivityCount; ++j) { - buf.WriteUInt32(j); // ActivityNumber - auto &activity = Tasks[TaskList[i]]->Activity[j]; - buf.WriteUInt32(activity.Type); // ActivityType - buf.WriteUInt32(0); // solo, group, raid? - buf.WriteString(activity.target_name); // max length 64, "target name" so like loot x foo from bar (this is bar) - - // this string is item names - buf.WriteLengthString(activity.item_list); - - buf.WriteUInt32(activity.GoalCount); // GoalCount - - // this string is skill IDs? probably one of the "use on" tasks - buf.WriteLengthString(activity.skill_list); - - // this string is spell IDs? probably one of the "use on" tasks - buf.WriteLengthString(activity.spell_list); - - //buf.WriteString(itoa(Tasks[TaskList[i]]->Activity[ActivityID].ZoneID)); - buf.WriteString(activity.zones); // Zone number in ascii max length 64, can be multiple with separated by ; - buf.WriteString(activity.desc_override); // max length 128 -- overrides the automatic descriptions - // this doesn't appear to be shown to the client at all and isn't the same as zones ... defaults to '0' though - buf.WriteString(activity.zones); // Zone number in ascii max length 64, probably can be separated by ; too, haven't found it used - } - } - - auto outapp = new EQApplicationPacket(OP_OpenNewTasksWindow, buf); - - c->QueuePacket(outapp); - safe_delete(outapp); - -} - -int TaskManager::GetActivityCount(int TaskID) { - - // Return the total number of activities in a particular task. - - if((TaskID>0) && (TaskIDActivityCount; - - return 0; - -} - -void TaskManager::ExplainTask(Client*c, int TaskID) { - - // TODO: This method is not finished (hardly started). It was intended to - // explain in English, what each activity did, conditions for step unlocking, etc. - // - return; - - if(!c) return; - - if((TaskID<=0) || (TaskID>=MAXTASKS)) { - c->Message(Chat::White, "TaskID out-of-range."); - return; - } - - if(Tasks[TaskID] == nullptr) { - c->Message(Chat::White, "Task does not exist."); - return; - } - - char Explanation[1000], *ptr; - c->Message(Chat::White, "Task %4i: Title: %s", TaskID, Tasks[TaskID]->Description.c_str()); - c->Message(Chat::White, "%3i Activities", Tasks[TaskID]->ActivityCount); - ptr = Explanation; - for(int i=0; iActivityCount; i++) { - - sprintf(ptr, "Act: %3i: ", i); ptr = ptr + strlen(ptr); - switch(Tasks[TaskID]->Activity[i].Type) { - case ActivityDeliver: - sprintf(ptr, "Deliver"); - break; - } - - } -} - -ClientTaskState::ClientTaskState() { - - ActiveTaskCount = 0; - LastCompletedTaskLoaded = 0; - CheckedTouchActivities = false; - - for (int i = 0; i < MAXACTIVEQUESTS; i++) { - ActiveQuests[i].slot = i; - ActiveQuests[i].TaskID = TASKSLOTEMPTY; - } - - ActiveTask.slot = 0; - ActiveTask.TaskID = TASKSLOTEMPTY; - // TODO: shared task -} - -ClientTaskState::~ClientTaskState() { -} - - -int ClientTaskState::GetActiveTaskID(int index) { - - // Return the TaskID from the client's specified Active Task slot. - - if((index<0) || (index>=MAXACTIVEQUESTS)) return 0; - - return ActiveQuests[index].TaskID; -} - -static void DeleteCompletedTaskFromDatabase(int charID, int taskID) { - - Log(Logs::General, Logs::Tasks, "[UPDATE] DeleteCompletedTasksFromDatabase. CharID = %i, TaskID = %i", charID, taskID); - - const std::string query = StringFormat("DELETE FROM completed_tasks WHERE charid=%i AND taskid = %i", charID, taskID); - auto results = database.QueryDatabase(query); - if(!results.Success()) { - return; - } - - Log(Logs::General, Logs::Tasks, "[UPDATE] Delete query %s", query.c_str()); -} - -bool ClientTaskState::UnlockActivities(int CharID, ClientTaskInformation &task_info) -{ - bool AllActivitiesComplete = true; - - TaskInformation* Task = taskmanager->Tasks[task_info.TaskID]; - - if (Task == nullptr) - return true; - - // On loading the client state, all activities that are not completed, are - // marked as hidden. For Sequential (non-stepped) mode, we mark the first - // activity as active if not complete. - Log(Logs::General, Logs::Tasks, "[UPDATE] CharID: %i Task: %i Sequence mode is %i", - CharID, task_info.TaskID, Task->SequenceMode); - - if (Task->SequenceMode == ActivitiesSequential) { - if (task_info.Activity[0].State != ActivityCompleted) - task_info.Activity[0].State = ActivityActive; - - // Enable the next Hidden task. - for (int i = 0; i < Task->ActivityCount; i++) { - if ((task_info.Activity[i].State == ActivityActive) && - (!Task->Activity[i].Optional)) { - AllActivitiesComplete = false; - break; - } - - if (task_info.Activity[i].State == ActivityHidden) { - task_info.Activity[i].State = ActivityActive; - AllActivitiesComplete = false; - break; - } - } - - if (AllActivitiesComplete && RuleB(TaskSystem, RecordCompletedTasks)) { - if (RuleB(TasksSystem, KeepOneRecordPerCompletedTask)) { - Log(Logs::General, Logs::Tasks, "[UPDATE] KeepOneRecord enabled"); - auto Iterator = CompletedTasks.begin(); - int ErasedElements = 0; - while (Iterator != CompletedTasks.end()) { - int TaskID = (*Iterator).TaskID; - if (TaskID == task_info.TaskID) { - Iterator = CompletedTasks.erase(Iterator); - ErasedElements++; - } else - ++Iterator; - } - - Log(Logs::General, Logs::Tasks, "[UPDATE] Erased Element count is %i", ErasedElements); - - if (ErasedElements) { - LastCompletedTaskLoaded -= ErasedElements; - DeleteCompletedTaskFromDatabase(CharID, task_info.TaskID); - } - } - - CompletedTaskInformation cti; - cti.TaskID = task_info.TaskID; - cti.CompletedTime = time(nullptr); - - for (int i = 0; i < Task->ActivityCount; i++) - cti.ActivityDone[i] = (task_info.Activity[i].State == ActivityCompleted); - - CompletedTasks.push_back(cti); - } - - Log(Logs::General, Logs::Tasks, "[UPDATE] Returning sequential task, AllActivitiesComplete is %i", - AllActivitiesComplete); - - return AllActivitiesComplete; - } - - // Stepped Mode - // TODO: This code is probably more complex than it needs to be - - bool CurrentStepComplete = true; - - Log(Logs::General, Logs::Tasks, "[UPDATE] Current Step is %i, Last Step is %i", task_info.CurrentStep, - Task->LastStep); - // If CurrentStep is -1, this is the first call to this method since loading the - // client state. Unlock all activities with a step number of 0 - - if (task_info.CurrentStep == -1) { - for (int i = 0; i < Task->ActivityCount; i++) { - if (Task->Activity[i].StepNumber == 0 && task_info.Activity[i].State == ActivityHidden) { - task_info.Activity[i].State = ActivityActive; - // task_info.Activity[i].Updated=true; - } - } - task_info.CurrentStep = 0; - } - - for (int Step = task_info.CurrentStep; Step <= Task->LastStep; Step++) { - for (int Activity = 0; Activity < Task->ActivityCount; Activity++) { - if (Task->Activity[Activity].StepNumber == (int)task_info.CurrentStep) { - if ((task_info.Activity[Activity].State != ActivityCompleted) && - (!Task->Activity[Activity].Optional)) { - CurrentStepComplete = false; - AllActivitiesComplete = false; - break; - } - } - } - if (!CurrentStepComplete) - break; - task_info.CurrentStep++; - } - - if (AllActivitiesComplete) { - if (RuleB(TaskSystem, RecordCompletedTasks)) { - // If we are only keeping one completed record per task, and the player has done - // the same task again, erase the previous completed entry for this task. - if (RuleB(TasksSystem, KeepOneRecordPerCompletedTask)) { - Log(Logs::General, Logs::Tasks, "[UPDATE] KeepOneRecord enabled"); - auto Iterator = CompletedTasks.begin(); - int ErasedElements = 0; - - while (Iterator != CompletedTasks.end()) { - int TaskID = (*Iterator).TaskID; - if (TaskID == task_info.TaskID) { - Iterator = CompletedTasks.erase(Iterator); - ErasedElements++; - } else - ++Iterator; - } - - Log(Logs::General, Logs::Tasks, "[UPDATE] Erased Element count is %i", ErasedElements); - - if (ErasedElements) { - LastCompletedTaskLoaded -= ErasedElements; - DeleteCompletedTaskFromDatabase(CharID, task_info.TaskID); - } - } - - CompletedTaskInformation cti; - cti.TaskID = task_info.TaskID; - cti.CompletedTime = time(nullptr); - - for (int i = 0; i < Task->ActivityCount; i++) - cti.ActivityDone[i] = (task_info.Activity[i].State == ActivityCompleted); - - CompletedTasks.push_back(cti); - } - return true; - } - - // Mark all non-completed tasks in the current step as active - // - for (int Activity = 0; Activity < Task->ActivityCount; Activity++) { - if ((Task->Activity[Activity].StepNumber == (int)task_info.CurrentStep) && - (task_info.Activity[Activity].State == ActivityHidden)) { - task_info.Activity[Activity].State = ActivityActive; - task_info.Activity[Activity].Updated = true; - } - } - - return false; -} - -void ClientTaskState::UpdateTasksOnKill(Client *c, int NPCTypeID) { - - UpdateTasksByNPC(c, ActivityKill, NPCTypeID); - -} - -bool ClientTaskState::UpdateTasksOnSpeakWith(Client *c, int NPCTypeID) { - - return UpdateTasksByNPC(c, ActivitySpeakWith, NPCTypeID); - -} - -bool ClientTaskState::UpdateTasksByNPC(Client *c, int ActivityType, int NPCTypeID) { - - int Ret = false; - - Log(Logs::General, Logs::Tasks, "[UPDATE] ClientTaskState::UpdateTasks for NPCTypeID: %d", NPCTypeID); - - // If the client has no tasks, there is nothing further to check. - - if (!taskmanager || (ActiveTaskCount == 0 && ActiveTask.TaskID == TASKSLOTEMPTY)) // could be better ... - return false; - - // loop over the union of tasks and quests - for (int i = 0; i < MAXACTIVEQUESTS + 1; i++) { - auto cur_task = &ActiveTasks[i]; - if (cur_task->TaskID == TASKSLOTEMPTY) - continue; - - // Check if there are any active kill activities for this task - - auto Task = taskmanager->Tasks[cur_task->TaskID]; - - if (Task == nullptr) - return false; - - for (int j = 0; j < Task->ActivityCount; j++) { - // We are not interested in completed or hidden activities - if (cur_task->Activity[j].State != ActivityActive) - continue; - // We are only interested in Kill activities - if (Task->Activity[j].Type != ActivityType) - continue; - // Is there a zone restriction on the activity ? - if (!Task->Activity[j].CheckZone(zone->GetZoneID())) { - Log(Logs::General, Logs::Tasks, - "[UPDATE] Char: %s Task: %i, Activity %i, Activity type %i for NPC %i failed zone " - "check", - c->GetName(), cur_task->TaskID, j, ActivityType, NPCTypeID); - continue; - } - // Is the activity to kill this type of NPC ? - switch (Task->Activity[j].GoalMethod) { - - case METHODSINGLEID: - if (Task->Activity[j].GoalID != NPCTypeID) - continue; - break; - - case METHODLIST: - if (!taskmanager->GoalListManager.IsInList(Task->Activity[j].GoalID, NPCTypeID)) - continue; - break; - - default: - // If METHODQUEST, don't update the activity here - continue; - } - // We found an active task to kill this type of NPC, so increment the done count - Log(Logs::General, Logs::Tasks, "[UPDATE] Calling increment done count ByNPC"); - IncrementDoneCount(c, Task, cur_task->slot, j); - Ret = true; - } - } - - return Ret; -} - -int ClientTaskState::ActiveSpeakTask(int NPCTypeID) { - - // This method is to be used from Perl quests only and returns the TaskID of the first - // active task found which has an active SpeakWith activity for this NPC. - - if (!taskmanager || (ActiveTaskCount == 0 && ActiveTask.TaskID == TASKSLOTEMPTY)) // could be better ... - return 0; - - // loop over the union of tasks and quests - for (int i = 0; i < MAXACTIVEQUESTS + 1; i++) { - auto cur_task = &ActiveTasks[i]; - if (cur_task->TaskID == TASKSLOTEMPTY) - continue; - - TaskInformation* Task = taskmanager->Tasks[cur_task->TaskID]; - - if (Task == nullptr) - continue; - - for (int j = 0; j < Task->ActivityCount; j++) { - // We are not interested in completed or hidden activities - if (cur_task->Activity[j].State != ActivityActive) - continue; - if (Task->Activity[j].Type != ActivitySpeakWith) - continue; - // Is there a zone restriction on the activity ? - if (!Task->Activity[j].CheckZone(zone->GetZoneID())) - continue; - // Is the activity to speak with this type of NPC ? - if (Task->Activity[j].GoalMethod == METHODQUEST && Task->Activity[j].GoalID == NPCTypeID) - return cur_task->TaskID; - } - } - return 0; -} - -int ClientTaskState::ActiveSpeakActivity(int NPCTypeID, int TaskID) { - - // This method is to be used from Perl quests only and returns the ActivityID of the first - // active activity found in the specified task which is to SpeakWith this NPC. - - if (!taskmanager || (ActiveTaskCount == 0 && ActiveTask.TaskID == TASKSLOTEMPTY)) // could be better ... - return -1; - if (TaskID <= 0 || TaskID >= MAXTASKS) - return -1; - - // loop over the union of tasks and quests - for (int i = 0; i < MAXACTIVEQUESTS + 1; i++) { - auto cur_task = &ActiveTasks[i]; - if (cur_task->TaskID != TaskID) - continue; - - TaskInformation* Task = taskmanager->Tasks[cur_task->TaskID]; - - if (Task == nullptr) - continue; - - for (int j = 0; j < Task->ActivityCount; j++) { - // We are not interested in completed or hidden activities - if (cur_task->Activity[j].State != ActivityActive) - continue; - if (Task->Activity[j].Type != ActivitySpeakWith) - continue; - // Is there a zone restriction on the activity ? - if (!Task->Activity[j].CheckZone(zone->GetZoneID())) - continue; - // Is the activity to speak with this type of NPC ? - if (Task->Activity[j].GoalMethod == METHODQUEST && Task->Activity[j].GoalID == NPCTypeID) - return j; - } - return 0; - } - return 0; -} - -void ClientTaskState::UpdateTasksForItem(Client *c, ActivityType Type, int ItemID, int Count) { - - // This method updates the client's task activities of the specified type which relate - // to the specified item. - // - // Type should be one of ActivityLoot, ActivityTradeSkill, ActivityFish or ActivityForage - - // If the client has no tasks, there is nothing further to check. - - Log(Logs::General, Logs::Tasks, "[UPDATE] ClientTaskState::UpdateTasksForItem(%d,%d)", Type, ItemID); - - if (!taskmanager || (ActiveTaskCount == 0 && ActiveTask.TaskID == TASKSLOTEMPTY)) // could be better ... - return; - - // loop over the union of tasks and quests - for (int i = 0; i < MAXACTIVEQUESTS + 1; i++) { - auto cur_task = &ActiveTasks[i]; - if (cur_task->TaskID == TASKSLOTEMPTY) - continue; - - // Check if there are any active loot activities for this task - - TaskInformation* Task = taskmanager->Tasks[cur_task->TaskID]; - - if (Task == nullptr) - return; - - for (int j = 0; j < Task->ActivityCount; j++) { - // We are not interested in completed or hidden activities - if (cur_task->Activity[j].State != ActivityActive) - continue; - // We are only interested in the ActivityType we were called with - if (Task->Activity[j].Type != (int)Type) - continue; - // Is there a zone restriction on the activity ? - if (!Task->Activity[j].CheckZone(zone->GetZoneID())) { - Log(Logs::General, Logs::Tasks, "[UPDATE] Char: %s Activity type %i for Item %i failed zone check", - c->GetName(), Type, ItemID); - continue; - } - // Is the activity related to this item ? - // - switch(Task->Activity[j].GoalMethod) { - - case METHODSINGLEID: - if(Task->Activity[j].GoalID != ItemID) continue; - break; - - case METHODLIST: - if(!taskmanager->GoalListManager.IsInList(Task->Activity[j].GoalID, ItemID)) continue; - break; - - default: - // If METHODQUEST, don't update the activity here - continue; - } - // We found an active task related to this item, so increment the done count - Log(Logs::General, Logs::Tasks, "[UPDATE] Calling increment done count ForItem"); - IncrementDoneCount(c, Task, cur_task->slot, j, Count); - } - } - - return; -} - -void ClientTaskState::UpdateTasksOnExplore(Client *c, int ExploreID) -{ - - // If the client has no tasks, there is nothing further to check. - - Log(Logs::General, Logs::Tasks, "[UPDATE] ClientTaskState::UpdateTasksOnExplore(%i)", ExploreID); - if (!taskmanager || (ActiveTaskCount == 0 && ActiveTask.TaskID == TASKSLOTEMPTY)) // could be better ... - return; - - // loop over the union of tasks and quests - for (int i = 0; i < MAXACTIVEQUESTS + 1; i++) { - auto cur_task = &ActiveTasks[i]; - if (cur_task->TaskID == TASKSLOTEMPTY) - continue; - - // Check if there are any active explore activities for this task - - TaskInformation *Task = taskmanager->Tasks[cur_task->TaskID]; - - if (Task == nullptr) - return; - - for (int j = 0; j < Task->ActivityCount; j++) { - // We are not interested in completed or hidden activities - if (cur_task->Activity[j].State != ActivityActive) - continue; - // We are only interested in explore activities - if (Task->Activity[j].Type != ActivityExplore) - continue; - if (!Task->Activity[j].CheckZone(zone->GetZoneID())) { - Log(Logs::General, Logs::Tasks, - "[UPDATE] Char: %s Explore exploreid %i failed zone check", c->GetName(), - ExploreID); - continue; - } - // Is the activity to explore this area id ? - switch (Task->Activity[j].GoalMethod) { - - case METHODSINGLEID: - if (Task->Activity[j].GoalID != ExploreID) - continue; - break; - - case METHODLIST: - if (!taskmanager->GoalListManager.IsInList(Task->Activity[j].GoalID, ExploreID)) - continue; - break; - - default: - // If METHODQUEST, don't update the activity here - continue; - } - // We found an active task to explore this area, so set done count to goal count - // (Only a goal count of 1 makes sense for explore activities?) - Log(Logs::General, Logs::Tasks, "[UPDATE] Increment on explore"); - IncrementDoneCount(c, Task, cur_task->slot, j, - Task->Activity[j].GoalCount - cur_task->Activity[j].DoneCount); - } - } - - return; -} - -bool ClientTaskState::UpdateTasksOnDeliver(Client *c, std::list &Items, int Cash, int NPCTypeID) -{ - bool Ret = false; - - Log(Logs::General, Logs::Tasks, "[UPDATE] ClientTaskState::UpdateTasksForOnDeliver(%d)", NPCTypeID); - - if (!taskmanager || (ActiveTaskCount == 0 && ActiveTask.TaskID == TASKSLOTEMPTY)) // could be better ... - return false; - - // loop over the union of tasks and quests - for (int i = 0; i < MAXACTIVEQUESTS + 1; i++) { - auto cur_task = &ActiveTasks[i]; - if (cur_task->TaskID == TASKSLOTEMPTY) - continue; - - // Check if there are any active deliver activities for this task - - TaskInformation *Task = taskmanager->Tasks[cur_task->TaskID]; - - if (Task == nullptr) - return false; - - for (int j = 0; j < Task->ActivityCount; j++) { - // We are not interested in completed or hidden activities - if (cur_task->Activity[j].State != ActivityActive) - continue; - // We are only interested in Deliver activities - if (Task->Activity[j].Type != ActivityDeliver && Task->Activity[j].Type != ActivityGiveCash) - continue; - // Is there a zone restriction on the activity ? - if (!Task->Activity[j].CheckZone(zone->GetZoneID())) { - Log(Logs::General, Logs::Tasks, - "[UPDATE] Char: %s Deliver activity failed zone check (current zone %i, need zone " - "%s", - c->GetName(), zone->GetZoneID(), Task->Activity[j].zones.c_str()); - continue; - } - // Is the activity to deliver to this NPCTypeID ? - if (Task->Activity[j].DeliverToNPC != NPCTypeID) - continue; - // Is the activity related to these items ? - // - if ((Task->Activity[j].Type == ActivityGiveCash) && Cash) { - Log(Logs::General, Logs::Tasks, "[UPDATE] Increment on GiveCash"); - IncrementDoneCount(c, Task, i, j, Cash); - Ret = true; - } else { - for (auto &k : Items) { - switch (Task->Activity[j].GoalMethod) { - - case METHODSINGLEID: - if (Task->Activity[j].GoalID != k->GetID()) - continue; - break; - - case METHODLIST: - if (!taskmanager->GoalListManager.IsInList(Task->Activity[j].GoalID, - k->GetID())) - continue; - break; - - default: - // If METHODQUEST, don't update the activity here - continue; - } - // We found an active task related to this item, so increment the done count - Log(Logs::General, Logs::Tasks, "[UPDATE] Increment on GiveItem"); - IncrementDoneCount(c, Task, cur_task->slot, j, k->GetCharges() <= 0 ? 1 : k->GetCharges()); - Ret = true; - } - } - } - } - - return Ret; -} - -void ClientTaskState::UpdateTasksOnTouch(Client *c, int ZoneID) -{ - // If the client has no tasks, there is nothing further to check. - - Log(Logs::General, Logs::Tasks, "[UPDATE] ClientTaskState::UpdateTasksOnTouch(%i)", ZoneID); - if (!taskmanager || (ActiveTaskCount == 0 && ActiveTask.TaskID == TASKSLOTEMPTY)) // could be better ... - return; - - // loop over the union of tasks and quests - for (int i = 0; i < MAXACTIVEQUESTS + 1; i++) { - auto cur_task = &ActiveTasks[i]; - if (cur_task->TaskID == TASKSLOTEMPTY) - continue; - - // Check if there are any active explore activities for this task - - TaskInformation *Task = taskmanager->Tasks[cur_task->TaskID]; - - if (Task == nullptr) - return; - - for (int j = 0; j < Task->ActivityCount; j++) { - // We are not interested in completed or hidden activities - if (cur_task->Activity[j].State != ActivityActive) - continue; - // We are only interested in touch activities - if (Task->Activity[j].Type != ActivityTouch) - continue; - if (Task->Activity[j].GoalMethod != METHODSINGLEID) - continue; - if (!Task->Activity[j].CheckZone(ZoneID)) { - Log(Logs::General, Logs::Tasks, "[UPDATE] Char: %s Touch activity failed zone check", - c->GetName()); - continue; - } - // We found an active task to zone into this zone, so set done count to goal count - // (Only a goal count of 1 makes sense for touch activities?) - Log(Logs::General, Logs::Tasks, "[UPDATE] Increment on Touch"); - IncrementDoneCount(c, Task, cur_task->slot, j, - Task->Activity[j].GoalCount - cur_task->Activity[j].DoneCount); - } - } - - return; -} - -void ClientTaskState::IncrementDoneCount(Client *c, TaskInformation *Task, int TaskIndex, int ActivityID, int Count, - bool ignore_quest_update) -{ - Log(Logs::General, Logs::Tasks, "[UPDATE] IncrementDoneCount"); - - auto info = GetClientTaskInfo(Task->type, TaskIndex); - - if (info == nullptr) - return; - - info->Activity[ActivityID].DoneCount += Count; - - if(info->Activity[ActivityID].DoneCount > Task->Activity[ActivityID].GoalCount) - info->Activity[ActivityID].DoneCount = Task->Activity[ActivityID].GoalCount; - - if (!ignore_quest_update){ - char buf[24]; - snprintf(buf, 23, "%d %d %d", info->Activity[ActivityID].DoneCount, info->Activity[ActivityID].ActivityID, info->TaskID); - buf[23] = '\0'; - parse->EventPlayer(EVENT_TASK_UPDATE, c, buf, 0); - } - - info->Activity[ActivityID].Updated=true; - // Have we reached the goal count for this activity ? - if(info->Activity[ActivityID].DoneCount >= Task->Activity[ActivityID].GoalCount) { - Log(Logs::General, Logs::Tasks, "[UPDATE] Done (%i) = Goal (%i) for Activity %i", - info->Activity[ActivityID].DoneCount, - Task->Activity[ActivityID].GoalCount, - ActivityID); - - // Flag the activity as complete - info->Activity[ActivityID].State = ActivityCompleted; - // Unlock subsequent activities for this task - bool TaskComplete = UnlockActivities(c->CharacterID(), *info); - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskCompleted is %i", TaskComplete); - // and by the 'Task Stage Completed' message - c->SendTaskActivityComplete(info->TaskID, ActivityID, TaskIndex, Task->type); - // Send the updated task/activity list to the client - taskmanager->SendSingleActiveTaskToClient(c, *info, TaskComplete, false); - // Inform the client the task has been updated, both by a chat message - c->Message(Chat::White, "Your task '%s' has been updated.", Task->Title.c_str()); - - if(Task->Activity[ActivityID].GoalMethod != METHODQUEST) { - if (!ignore_quest_update){ - char buf[24]; - snprintf(buf, 23, "%d %d", info->TaskID, info->Activity[ActivityID].ActivityID); - buf[23] = '\0'; - parse->EventPlayer(EVENT_TASK_STAGE_COMPLETE, c, buf, 0); - } - /* QS: PlayerLogTaskUpdates :: Update */ - if (RuleB(QueryServ, PlayerLogTaskUpdates)){ - std::string event_desc = StringFormat("Task Stage Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", info->TaskID, info->Activity[ActivityID].ActivityID, info->Activity[ActivityID].DoneCount, c->GetZoneID(), c->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Task_Updates, c->CharacterID(), event_desc); - } - } - - // If this task is now complete, the Completed tasks will have been - // updated in UnlockActivities. Send the completed task list to the - // client. This is the same sequence the packets are sent on live. - if(TaskComplete) { - char buf[24]; - snprintf(buf, 23, "%d %d %d", info->Activity[ActivityID].DoneCount, info->Activity[ActivityID].ActivityID, info->TaskID); - buf[23] = '\0'; - parse->EventPlayer(EVENT_TASK_COMPLETE, c, buf, 0); - - /* QS: PlayerLogTaskUpdates :: Complete */ - if (RuleB(QueryServ, PlayerLogTaskUpdates)){ - std::string event_desc = StringFormat("Task Complete :: taskid:%i activityid:%i donecount:%i in zoneid:%i instid:%i", info->TaskID, info->Activity[ActivityID].ActivityID, info->Activity[ActivityID].DoneCount, c->GetZoneID(), c->GetInstanceID()); - QServ->PlayerLogEvent(Player_Log_Task_Updates, c->CharacterID(), event_desc); - } - - taskmanager->SendCompletedTasksToClient(c, this); - c->SendTaskActivityComplete(info->TaskID, 0, TaskIndex, Task->type, 0); - taskmanager->SaveClientState(c, this); - //c->SendTaskComplete(TaskIndex); - c->CancelTask(TaskIndex, Task->type); - //if(Task->RewardMethod != METHODQUEST) RewardTask(c, Task); - // If Experience and/or cash rewards are set, reward them from the task even if RewardMethod is METHODQUEST - RewardTask(c, Task); - //RemoveTask(c, TaskIndex); - - } - - } else { - // Send an update packet for this single activity - taskmanager->SendTaskActivityLong(c, info->TaskID, ActivityID, TaskIndex, - Task->Activity[ActivityID].Optional); - taskmanager->SaveClientState(c, this); - } -} - -void ClientTaskState::RewardTask(Client *c, TaskInformation *Task) { - - if(!Task || !c) return; - - const EQ::ItemData* Item; - std::vector RewardList; - - switch(Task->RewardMethod) { - - case METHODSINGLEID: - { - if(Task->RewardID) { - c->SummonItem(Task->RewardID); - Item = database.GetItem(Task->RewardID); - if(Item) - c->Message(Chat::Yellow, "You receive %s as a reward.", Item->Name); - } - break; - } - case METHODLIST: - { - RewardList = taskmanager->GoalListManager.GetListContents(Task->RewardID); - for(unsigned int i=0; iSummonItem(RewardList[i]); - Item = database.GetItem(RewardList[i]); - if(Item) - c->Message(Chat::Yellow, "You receive %s as a reward.", Item->Name); - } - break; - } - default: - { - // Nothing special done for METHODQUEST - break; - } - } - - if (!Task->completion_emote.empty()) - c->SendColoredText(Chat::Yellow, Task->completion_emote); // unsure if they use this packet or color, should work - - // just use normal NPC faction ID stuff - if (Task->faction_reward) - c->SetFactionLevel(c->CharacterID(), Task->faction_reward, c->GetBaseClass(), c->GetBaseRace(), c->GetDeity()); - - if(Task->CashReward) { - int Plat, Gold, Silver, Copper; - - Copper = Task->CashReward; - c->AddMoneyToPP(Copper, true); - - Plat = Copper / 1000; - Copper = Copper - (Plat * 1000); - Gold = Copper / 100; - Copper = Copper - (Gold * 100); - Silver = Copper / 10; - Copper = Copper - (Silver * 10); - - std::string CashMessage; - - if (Plat>0){ - CashMessage = "You receive "; - CashMessage += itoa(Plat); - CashMessage += " platinum"; - } - if (Gold>0){ - if (CashMessage.length()==0){ - CashMessage = "You receive "; - } - else{ - CashMessage += ","; - } - CashMessage += itoa(Gold); - CashMessage += " gold"; - } - if(Silver>0){ - if (CashMessage.length()==0){ - CashMessage = "You receive "; - } - else{ - CashMessage += ","; - } - CashMessage += itoa(Silver); - CashMessage += " silver"; - } - if(Copper>0){ - if (CashMessage.length()==0){ - CashMessage = "You receive "; - } - else{ - CashMessage += ","; - } - CashMessage += itoa(Copper); - CashMessage += " copper"; - } - CashMessage += " pieces."; - c->Message(Chat::Yellow,CashMessage.c_str()); - } - int32 EXPReward = Task->XPReward; - if(EXPReward > 0) { - c->AddEXP(EXPReward); - } - if(EXPReward < 0) { - uint32 PosReward = EXPReward * -1; - // Minimal Level Based Exp Reward Setting is 101 (1% exp at level 1) - if (PosReward > 100 && PosReward < 25700) { - uint8 MaxLevel = PosReward / 100; - uint8 ExpPercent = PosReward - (MaxLevel * 100); - c->AddLevelBasedExp(ExpPercent, MaxLevel); - } - } - - c->SendSound(); -} - -bool ClientTaskState::IsTaskActive(int TaskID) -{ - if (ActiveTask.TaskID == TaskID) - return true; - - if (ActiveTaskCount == 0 || TaskID == 0) - return false; - - for (int i = 0; i < MAXACTIVEQUESTS; i++) { - if (ActiveQuests[i].TaskID == TaskID) - return true; - } - - return false; -} - -void ClientTaskState::FailTask(Client *c, int TaskID) -{ - Log(Logs::General, Logs::Tasks, "[UPDATE] FailTask %i, ActiveTaskCount is %i", TaskID, ActiveTaskCount); - - if (ActiveTask.TaskID == TaskID) { - c->SendTaskFailed(TaskID, 0, TaskType::Task); - // Remove the task from the client - c->CancelTask(0, TaskType::Task); - return; - } - - // TODO: shared tasks - - if (ActiveTaskCount == 0) - return; - - for (int i = 0; i < MAXACTIVEQUESTS; i++) { - if (ActiveQuests[i].TaskID == TaskID) { - c->SendTaskFailed(ActiveQuests[i].TaskID, i, TaskType::Quest); - // Remove the task from the client - c->CancelTask(i, TaskType::Quest); - return; - } - } -} - -// TODO: Shared tasks -bool ClientTaskState::IsTaskActivityActive(int TaskID, int ActivityID) -{ - - Log(Logs::General, Logs::Tasks, "[UPDATE] ClientTaskState IsTaskActivityActive(%i, %i).", TaskID, ActivityID); - // Quick sanity check - if (ActivityID < 0) - return false; - if (ActiveTaskCount == 0 && ActiveTask.TaskID == TASKSLOTEMPTY) - return false; - - int ActiveTaskIndex = -1; - auto type = TaskType::Task; - - if (ActiveTask.TaskID == TaskID) - ActiveTaskIndex = 0; - - if (ActiveTaskIndex == -1) { - for (int i = 0; i < MAXACTIVEQUESTS; i++) { - if (ActiveQuests[i].TaskID == TaskID) { - ActiveTaskIndex = i; - type = TaskType::Quest; - break; - } - } - } - - // The client does not have this task - if (ActiveTaskIndex == -1) - return false; - - auto info = GetClientTaskInfo(type, ActiveTaskIndex); - - if (info == nullptr) - return false; - - TaskInformation *Task = taskmanager->Tasks[info->TaskID]; - - // The task is invalid - if (Task == nullptr) - return false; - - // The ActivityID is out of range - if (ActivityID >= Task->ActivityCount) - return false; - - Log(Logs::General, Logs::Tasks, "[UPDATE] ClientTaskState IsTaskActivityActive(%i, %i). State is %i ", TaskID, - ActivityID, info->Activity[ActivityID].State); - - return (info->Activity[ActivityID].State == ActivityActive); -} - -void ClientTaskState::UpdateTaskActivity(Client *c, int TaskID, int ActivityID, int Count, bool ignore_quest_update /*= false*/) -{ - - Log(Logs::General, Logs::Tasks, "[UPDATE] ClientTaskState UpdateTaskActivity(%i, %i, %i).", TaskID, ActivityID, - Count); - - // Quick sanity check - if (ActivityID < 0 || (ActiveTaskCount == 0 && ActiveTask.TaskID == TASKSLOTEMPTY)) - return; - - int ActiveTaskIndex = -1; - auto type = TaskType::Task; - - if (ActiveTask.TaskID == TaskID) - ActiveTaskIndex = 0; - - if (ActiveTaskIndex == -1) { - for (int i = 0; i < MAXACTIVEQUESTS; i++) { - if (ActiveQuests[i].TaskID == TaskID) { - ActiveTaskIndex = i; - type = TaskType::Quest; - break; - } - } - } - - // The client does not have this task - if (ActiveTaskIndex == -1) - return; - - auto info = GetClientTaskInfo(type, ActiveTaskIndex); - - if (info == nullptr) - return; - - TaskInformation *Task = taskmanager->Tasks[info->TaskID]; - - // The task is invalid - if (Task == nullptr) - return; - - // The ActivityID is out of range - if (ActivityID >= Task->ActivityCount) - return; - - // The Activity is not currently active - if (info->Activity[ActivityID].State == ActivityHidden) - return; - - Log(Logs::General, Logs::Tasks, "[UPDATE] Increment done count on UpdateTaskActivity %d %d", ActivityID, Count); - IncrementDoneCount(c, Task, ActiveTaskIndex, ActivityID, Count, ignore_quest_update); -} - -void ClientTaskState::ResetTaskActivity(Client *c, int TaskID, int ActivityID) -{ - Log(Logs::General, Logs::Tasks, "[RESET] ClientTaskState ResetTaskActivity(%i, %i).", TaskID, ActivityID); - - // Quick sanity check - if (ActivityID < 0 || (ActiveTaskCount == 0 && ActiveTask.TaskID == TASKSLOTEMPTY)) - return; - - int ActiveTaskIndex = -1; - auto type = TaskType::Task; - - if (ActiveTask.TaskID == TaskID) - ActiveTaskIndex = 0; - - if (ActiveTaskIndex == -1) { - for (int i = 0; i < MAXACTIVEQUESTS; i++) { - if (ActiveQuests[i].TaskID == TaskID) { - ActiveTaskIndex = i; - type = TaskType::Quest; - break; - } - } - } - - // The client does not have this task - if (ActiveTaskIndex == -1) - return; - - auto info = GetClientTaskInfo(type, ActiveTaskIndex); - - if (info == nullptr) - return; - - TaskInformation *Task = taskmanager->Tasks[info->TaskID]; - - // The task is invalid - if (Task == nullptr) - return; - - // The ActivityID is out of range - if (ActivityID >= Task->ActivityCount) - return; - - // The Activity is not currently active - if (info->Activity[ActivityID].State == ActivityHidden) - return; - - Log(Logs::General, Logs::Tasks, "[RESET] Increment done count on ResetTaskActivity"); - IncrementDoneCount(c, Task, ActiveTaskIndex, ActivityID, (info->Activity[ActivityID].DoneCount * -1), false); -} - -void ClientTaskState::ShowClientTasks(Client *c) -{ - c->Message(Chat::White, "Task Information:"); - if (ActiveTask.TaskID != TASKSLOTEMPTY) { - c->Message(Chat::White, "Task: %i %s", ActiveTask.TaskID, taskmanager->Tasks[ActiveTask.TaskID]->Title.c_str()); - c->Message(Chat::White, " Description: [%s]\n", taskmanager->Tasks[ActiveTask.TaskID]->Description.c_str()); - for (int j = 0; j < taskmanager->GetActivityCount(ActiveTask.TaskID); j++) { - c->Message(Chat::White, " Activity: %2d, DoneCount: %2d, Status: %d (0=Hidden, 1=Active, 2=Complete)", - ActiveTask.Activity[j].ActivityID, ActiveTask.Activity[j].DoneCount, - ActiveTask.Activity[j].State); - } - } - - for (int i = 0; i < MAXACTIVEQUESTS; i++) { - if (ActiveQuests[i].TaskID == TASKSLOTEMPTY) - continue; - - c->Message(Chat::White, "Quest: %i %s", ActiveQuests[i].TaskID, - taskmanager->Tasks[ActiveQuests[i].TaskID]->Title.c_str()); - c->Message(Chat::White, " Description: [%s]\n", taskmanager->Tasks[ActiveQuests[i].TaskID]->Description.c_str()); - for (int j = 0; j < taskmanager->GetActivityCount(ActiveQuests[i].TaskID); j++) { - c->Message(Chat::White, " Activity: %2d, DoneCount: %2d, Status: %d (0=Hidden, 1=Active, 2=Complete)", - ActiveQuests[i].Activity[j].ActivityID, ActiveQuests[i].Activity[j].DoneCount, - ActiveQuests[i].Activity[j].State); - } - } -} - -// TODO: Shared Task -int ClientTaskState::TaskTimeLeft(int TaskID) -{ - if (ActiveTask.TaskID == TaskID) { - int Now = time(nullptr); - - TaskInformation *Task = taskmanager->Tasks[TaskID]; - - if (Task == nullptr) - return -1; - - if (!Task->Duration) - return -1; - - int TimeLeft = (ActiveTask.AcceptedTime + Task->Duration - Now); - - return (TimeLeft > 0 ? TimeLeft : 0); - } - - if (ActiveTaskCount == 0) - return -1; - - for (int i = 0; i < MAXACTIVEQUESTS; i++) { - - if (ActiveQuests[i].TaskID != TaskID) - continue; - - int Now = time(nullptr); - - TaskInformation *Task = taskmanager->Tasks[ActiveQuests[i].TaskID]; - - if (Task == nullptr) - return -1; - - if (!Task->Duration) - return -1; - - int TimeLeft = (ActiveQuests[i].AcceptedTime + Task->Duration - Now); - - // If Timeleft is negative, return 0, else return the number of seconds left - - return (TimeLeft > 0 ? TimeLeft : 0); - } - - return -1; -} - -int ClientTaskState::IsTaskCompleted(int TaskID) { - - // Returns: -1 if RecordCompletedTasks is not true - // +1 if the task has been completed - // 0 if the task has not been completed - - if(!(RuleB(TaskSystem, RecordCompletedTasks))) return -1; - - for(unsigned int i=0; i= MAXTASKS)) return false; - - TaskInformation* Task = taskmanager->Tasks[TaskID]; - - if(Task == nullptr) return false; - - return Task->Repeatable; -} - -bool ClientTaskState::TaskOutOfTime(TaskType type, int Index) -{ - // Returns true if the Task in the specified slot has a time limit that has been exceeded. - auto info = GetClientTaskInfo(type, Index); - - if (info == nullptr) - return false; - - // make sure the TaskID is at least maybe in our array - if (info->TaskID <= 0 || info->TaskID >= MAXTASKS) - return false; - - int Now = time(nullptr); - - TaskInformation *Task = taskmanager->Tasks[info->TaskID]; - - if (Task == nullptr) - return false; - - return (Task->Duration && (info->AcceptedTime + Task->Duration <= Now)); -} - -void ClientTaskState::TaskPeriodicChecks(Client *c) -{ - if (ActiveTask.TaskID != TASKSLOTEMPTY) { - if (TaskOutOfTime(TaskType::Task, 0)) { - // Send Red Task Failed Message - c->SendTaskFailed(ActiveTask.TaskID, 0, TaskType::Task); - // Remove the task from the client - c->CancelTask(0, TaskType::Task); - // It is a conscious decision to only fail one task per call to this method, - // otherwise the player will not see all the failed messages where multiple - // tasks fail at the same time. - return; - } - } - - // TODO: shared tasks -- although that will probably be manager in world checking and telling zones to fail us - - if (ActiveTaskCount == 0) - return; - - // Check for tasks that have failed because they have not been completed in the specified time - // - for (int i = 0; i < MAXACTIVEQUESTS; i++) { - if (ActiveQuests[i].TaskID == TASKSLOTEMPTY) - continue; - - if (TaskOutOfTime(TaskType::Quest, i)) { - // Send Red Task Failed Message - c->SendTaskFailed(ActiveQuests[i].TaskID, i, TaskType::Quest); - // Remove the task from the client - c->CancelTask(i, TaskType::Quest); - // It is a conscious decision to only fail one task per call to this method, - // otherwise the player will not see all the failed messages where multiple - // tasks fail at the same time. - break; - } - } - - // Check for activities that require zoning into a specific zone. - // This is done in this method because it gives an extra few seconds for the client screen to display - // the zone before we send the 'Task Activity Completed' message. - // - if (!CheckedTouchActivities) { - UpdateTasksOnTouch(c, zone->GetZoneID()); - CheckedTouchActivities = true; + if (task_state) { + task_state->CancelAllTasks(this); + safe_delete(task_state); } } @@ -2493,7 +48,7 @@ void Client::SendTaskComplete(int TaskIndex) { tcs = (TaskComplete_Struct*)outapp->pBuffer; // I have seen unknown0 as non-zero. It always seems to match the value in the first word of the - // Task Activity Complete packet sent immediately prior to it. + // Task activity_information Complete packet sent immediately prior to it. //tcs->unknown00 = 0x00000000; tcs->unknown00 = TaskIndex; // I have only seen 0x00000002 in the next field. This is a common 'unknown' value in the task packets. @@ -2511,1093 +66,58 @@ void Client::SendTaskComplete(int TaskIndex) { } #endif -void ClientTaskState::SendTaskHistory(Client *c, int TaskIndex) { - - Log(Logs::General, Logs::Tasks, "[UPDATE] Task History Requested for Completed Task Index %i", TaskIndex); - - // We only sent the most recent 50 completed tasks, so we need to offset the Index the client sent to us. - - int AdjustedTaskIndex = TaskIndex; - - if(CompletedTasks.size() > 50) - AdjustedTaskIndex += (CompletedTasks.size() - 50); - - if((AdjustedTaskIndex < 0) || (AdjustedTaskIndex >= (int)CompletedTasks.size())) return; - - int TaskID = CompletedTasks[AdjustedTaskIndex].TaskID; - - if((TaskID < 0) || (TaskID > MAXTASKS)) return; - - TaskInformation* Task = taskmanager->Tasks[TaskID]; - - if(Task == nullptr) return; - - TaskHistoryReplyHeader_Struct* ths; - TaskHistoryReplyData1_Struct* thd1; - TaskHistoryReplyData2_Struct* thd2; - - char *Ptr; - - int CompletedActivityCount = 0;; - - int PacketLength = sizeof(TaskHistoryReplyHeader_Struct); - - for(int i=0; iActivityCount; i++) { - if(CompletedTasks[AdjustedTaskIndex].ActivityDone[i]) { - CompletedActivityCount++; - PacketLength = PacketLength + sizeof(TaskHistoryReplyData1_Struct) + - Task->Activity[i].target_name.size() + 1 + - Task->Activity[i].item_list.size() + 1 + - sizeof(TaskHistoryReplyData2_Struct) + - Task->Activity[i].desc_override.size() + 1; - } - } - - auto outapp = new EQApplicationPacket(OP_TaskHistoryReply, PacketLength); - - ths = (TaskHistoryReplyHeader_Struct*)outapp->pBuffer; - - // We use the TaskIndex the client sent in the request - ths->TaskID = TaskIndex; - - ths->ActivityCount = CompletedActivityCount; - - Ptr = (char *) ths + sizeof(TaskHistoryReplyHeader_Struct); - - for(int i=0; iActivityCount; i++) { - if(CompletedTasks[AdjustedTaskIndex].ActivityDone[i]) { - thd1 = (TaskHistoryReplyData1_Struct*)Ptr; - thd1->ActivityType = Task->Activity[i].Type; - Ptr = (char *)thd1 + sizeof(TaskHistoryReplyData1_Struct); - VARSTRUCT_ENCODE_STRING(Ptr, Task->Activity[i].target_name.c_str()); - VARSTRUCT_ENCODE_STRING(Ptr, Task->Activity[i].item_list.c_str()); - thd2 = (TaskHistoryReplyData2_Struct*)Ptr; - thd2->GoalCount = Task->Activity[i].GoalCount; - thd2->unknown04 = 0xffffffff; - thd2->unknown08 = 0xffffffff; - thd2->ZoneID = Task->Activity[i].ZoneIDs.empty() ? 0 : Task->Activity[i].ZoneIDs.front(); - thd2->unknown16 = 0x00000000; - Ptr = (char *)thd2 + sizeof(TaskHistoryReplyData2_Struct); - VARSTRUCT_ENCODE_STRING(Ptr, Task->Activity[i].desc_override.c_str()); - } - } - - - c->QueuePacket(outapp); - safe_delete(outapp); - - - -} - -void Client::SendTaskActivityComplete(int TaskID, int ActivityID, int TaskIndex, TaskType type, int TaskIncomplete) +void Client::SendTaskActivityComplete( + int task_id, + int activity_id, + int task_index, + TaskType task_type, + int task_incomplete +) { - // 0x54eb - - TaskActivityComplete_Struct* tac; + TaskActivityComplete_Struct *task_activity_complete; auto outapp = new EQApplicationPacket(OP_TaskActivityComplete, sizeof(TaskActivityComplete_Struct)); - tac = (TaskActivityComplete_Struct*)outapp->pBuffer; - - tac->TaskIndex = TaskIndex; - tac->TaskType = static_cast(type); - tac->TaskID = TaskID; - tac->ActivityID = ActivityID; - tac->task_completed = 0x00000001; - tac->stage_complete = TaskIncomplete; + task_activity_complete = (TaskActivityComplete_Struct *) outapp->pBuffer; + task_activity_complete->TaskIndex = task_index; + task_activity_complete->TaskType = static_cast(task_type); + task_activity_complete->TaskID = task_id; + task_activity_complete->ActivityID = activity_id; + task_activity_complete->task_completed = 0x00000001; + task_activity_complete->stage_complete = task_incomplete; QueuePacket(outapp); safe_delete(outapp); } -void Client::SendTaskFailed(int TaskID, int TaskIndex, TaskType type) +void Client::SendTaskFailed(int task_id, int task_index, TaskType task_type) { // 0x54eb char buf[24]; - snprintf(buf, 23, "%d", TaskID); + snprintf(buf, 23, "%d", task_id); buf[23] = '\0'; parse->EventPlayer(EVENT_TASK_FAIL, this, buf, 0); - TaskActivityComplete_Struct* tac; + TaskActivityComplete_Struct *task_activity_complete; auto outapp = new EQApplicationPacket(OP_TaskActivityComplete, sizeof(TaskActivityComplete_Struct)); - tac = (TaskActivityComplete_Struct*)outapp->pBuffer; + task_activity_complete = (TaskActivityComplete_Struct *) outapp->pBuffer; + task_activity_complete->TaskIndex = task_index; + task_activity_complete->TaskType = static_cast(task_type); + task_activity_complete->TaskID = task_id; + task_activity_complete->ActivityID = 0; + task_activity_complete->task_completed = 0; //Fail + task_activity_complete->stage_complete = 0; // 0 for task complete or failed. - tac->TaskIndex = TaskIndex; - tac->TaskType = static_cast(type); - tac->TaskID = TaskID; - tac->ActivityID = 0; - tac->task_completed = 0; //Fail - tac->stage_complete = 0; // 0 for task complete or failed. - - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskFailed"); + LogTasks("[SendTaskFailed] Sending failure to client [{}]", GetCleanName()); QueuePacket(outapp); safe_delete(outapp); } -void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *State) { - int PacketLength = 4; - - //vector::const_iterator iterator; - - // The client only display the first 50 Completed Tasks send, so send the 50 most recent - int FirstTaskToSend = 0; - int LastTaskToSend = State->CompletedTasks.size(); - - if(State->CompletedTasks.size() > 50) - FirstTaskToSend = State->CompletedTasks.size() - 50; - - Log(Logs::General, Logs::Tasks, "[UPDATE] Completed Task Count: %i, First Task to send is %i, Last is %i", - State->CompletedTasks.size(), FirstTaskToSend, LastTaskToSend); - /* - for(iterator=State->CompletedTasks.begin(); iterator!=State->CompletedTasks.end(); iterator++) { - int TaskID = (*iterator).TaskID; - if(Tasks[TaskID] == nullptr) continue; - PacketLength = PacketLength + 8 + strlen(Tasks[TaskID]->Title) + 1; - } - */ - for(int i = FirstTaskToSend; iCompletedTasks[i].TaskID; - if(Tasks[TaskID] == nullptr) continue; - PacketLength = PacketLength + 8 + Tasks[TaskID]->Title.size() + 1; - } - - auto outapp = new EQApplicationPacket(OP_CompletedTasks, PacketLength); - char *buf = (char*)outapp->pBuffer; - - //*(uint32 *)buf = State->CompletedTasks.size(); - *(uint32 *)buf = LastTaskToSend - FirstTaskToSend; - buf = buf + 4; - //for(iterator=State->CompletedTasks.begin(); iterator!=State->CompletedTasks.end(); iterator++) { - // int TaskID = (*iterator).TaskID; - for(int i = FirstTaskToSend; iCompletedTasks[i].TaskID; - if(Tasks[TaskID] == nullptr) continue; - *(uint32 *)buf = TaskID; - buf = buf + 4; - - sprintf(buf, "%s", Tasks[TaskID]->Title.c_str()); - buf = buf + strlen(buf) + 1; - //*(uint32 *)buf = (*iterator).CompletedTime; - *(uint32 *)buf = State->CompletedTasks[i].CompletedTime; - buf = buf + 4; - } - - - c->QueuePacket(outapp); - safe_delete(outapp); -} - - - -void TaskManager::SendTaskActivityShort(Client *c, int TaskID, int ActivityID, int ClientTaskIndex) -{ - // This Activity Packet is sent for activities that have not yet been unlocked and appear as ??? - // in the client. - - TaskActivityShort_Struct* tass; - - if (c->ClientVersionBit() & EQ::versions::maskRoFAndLater) - { - auto outapp = new EQApplicationPacket(OP_TaskActivity, 25); - outapp->WriteUInt32(ClientTaskIndex); - outapp->WriteUInt32(static_cast(Tasks[TaskID]->type)); - outapp->WriteUInt32(TaskID); - outapp->WriteUInt32(ActivityID); - outapp->WriteUInt32(0); - outapp->WriteUInt32(0xffffffff); - outapp->WriteUInt8(0); - c->FastQueuePacket(&outapp); - - return; - } - - auto outapp = new EQApplicationPacket(OP_TaskActivity, sizeof(TaskActivityShort_Struct)); - - tass = (TaskActivityShort_Struct*)outapp->pBuffer; - - tass->TaskSequenceNumber = ClientTaskIndex; - tass->unknown2 = static_cast(Tasks[TaskID]->type); - tass->TaskID = TaskID; - tass->ActivityID = ActivityID; - tass->unknown3 = 0x000000; - tass->ActivityType = 0xffffffff; - tass->unknown4 = 0x00000000; - - - c->QueuePacket(outapp); - safe_delete(outapp); -} - - - -void TaskManager::SendTaskActivityLong(Client *c, int TaskID, int ActivityID, int ClientTaskIndex, bool Optional, bool TaskComplete) { - - if (c->ClientVersion() >= EQ::versions::ClientVersion::RoF) - { - SendTaskActivityNew(c, TaskID, ActivityID, ClientTaskIndex, Optional, TaskComplete); - return; - } - - SerializeBuffer buf(100); - - buf.WriteUInt32(ClientTaskIndex); - buf.WriteUInt32(static_cast(Tasks[TaskID]->type)); - buf.WriteUInt32(TaskID); - buf.WriteUInt32(ActivityID); - buf.WriteUInt32(0); // unknown3 - - // We send our 'internal' types as ActivityCastOn. text3 should be set to the activity description, so it makes - // no difference to the client. All activity updates will be done based on our interal activity types. - if((Tasks[TaskID]->Activity[ActivityID].Type > 0) && Tasks[TaskID]->Activity[ActivityID].Type < 100) - buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].Type); - else - buf.WriteUInt32(ActivityCastOn); // w/e! - - buf.WriteUInt32(Optional); - buf.WriteUInt32(0); // solo, group, raid - - buf.WriteString(Tasks[TaskID]->Activity[ActivityID].target_name); // target name string - buf.WriteString(Tasks[TaskID]->Activity[ActivityID].item_list); // item name list - - if(Tasks[TaskID]->Activity[ActivityID].Type != ActivityGiveCash) - buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].GoalCount); - else - // For our internal type GiveCash, where the goal count has the amount of cash that must be given, - // we don't want the donecount and goalcount fields cluttered up with potentially large numbers, so we just - // send a goalcount of 1, and a bit further down, a donecount of 1 if the activity is complete, 0 otherwise. - // The text3 field should decribe the exact activity goal, e.g. give 3500gp to Hasten Bootstrutter. - buf.WriteUInt32(1); - - buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].skill_id); - buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].spell_id); - buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].ZoneIDs.empty() ? 0 : Tasks[TaskID]->Activity[ActivityID].ZoneIDs.front()); - buf.WriteUInt32(0); - - buf.WriteString(Tasks[TaskID]->Activity[ActivityID].desc_override); - - if(Tasks[TaskID]->Activity[ActivityID].Type != ActivityGiveCash) - buf.WriteUInt32(c->GetTaskActivityDoneCount(Tasks[TaskID]->type, ClientTaskIndex, ActivityID)); - else - // For internal activity types, DoneCount is either 1 if the activity is complete, 0 otherwise. - buf.WriteUInt32((c->GetTaskActivityDoneCount(Tasks[TaskID]->type, ClientTaskIndex, ActivityID) >= Tasks[TaskID]->Activity[ActivityID].GoalCount)); - - buf.WriteUInt32(1); // unknown - - auto outapp = new EQApplicationPacket(OP_TaskActivity, buf); - - c->QueuePacket(outapp); - safe_delete(outapp); - -} - -// Used only by RoF+ Clients -void TaskManager::SendTaskActivityNew(Client *c, int TaskID, int ActivityID, int ClientTaskIndex, bool Optional, bool TaskComplete) -{ - SerializeBuffer buf(100); - - buf.WriteUInt32(ClientTaskIndex); // TaskSequenceNumber - buf.WriteUInt32(static_cast(Tasks[TaskID]->type)); // task type - buf.WriteUInt32(TaskID); - buf.WriteUInt32(ActivityID); - buf.WriteUInt32(0); // unknown3 - - // We send our 'internal' types as ActivityCastOn. text3 should be set to the activity description, so it makes - // no difference to the client. All activity updates will be done based on our interal activity types. - if((Tasks[TaskID]->Activity[ActivityID].Type > 0) && Tasks[TaskID]->Activity[ActivityID].Type < 100) - buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].Type); - else - buf.WriteUInt32(ActivityCastOn); // w/e! - - buf.WriteUInt8(Optional); - buf.WriteUInt32(0); // solo, group, raid - - // One of these unknown fields maybe related to the 'Use On' activity types - buf.WriteString(Tasks[TaskID]->Activity[ActivityID].target_name); // target name string - - buf.WriteLengthString(Tasks[TaskID]->Activity[ActivityID].item_list); // item name list - - // Goal Count - if(Tasks[TaskID]->Activity[ActivityID].Type != ActivityGiveCash) - buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].GoalCount); - else - buf.WriteUInt32(1); // GoalCount - - // skill ID list ; separated - buf.WriteLengthString(Tasks[TaskID]->Activity[ActivityID].skill_list); - - // spelll ID list ; separated -- unsure wtf we're doing here - buf.WriteLengthString(Tasks[TaskID]->Activity[ActivityID].spell_list); - - buf.WriteString(Tasks[TaskID]->Activity[ActivityID].zones); - buf.WriteUInt32(0); // unknown7 - - buf.WriteString(Tasks[TaskID]->Activity[ActivityID].desc_override); // description override - - if(Tasks[TaskID]->Activity[ActivityID].Type != ActivityGiveCash) - buf.WriteUInt32(c->GetTaskActivityDoneCount(Tasks[TaskID]->type, ClientTaskIndex, ActivityID)); // DoneCount - else - // For internal activity types, DoneCount is either 1 if the activity is complete, 0 otherwise. - buf.WriteUInt32((c->GetTaskActivityDoneCount(Tasks[TaskID]->type, ClientTaskIndex, ActivityID) >= Tasks[TaskID]->Activity[ActivityID].GoalCount)); - - buf.WriteUInt8(1); // unknown9 - - buf.WriteString(Tasks[TaskID]->Activity[ActivityID].zones); - - auto outapp = new EQApplicationPacket(OP_TaskActivity, buf); - - c->QueuePacket(outapp); - safe_delete(outapp); - -} - -void TaskManager::SendActiveTasksToClient(Client *c, bool TaskComplete) -{ - auto state = c->GetTaskState(); - if (!state) - return; - - for (int TaskIndex = 0; TaskIndex < MAXACTIVEQUESTS + 1; TaskIndex++) { - int TaskID = state->ActiveTasks[TaskIndex].TaskID; - if ((TaskID == 0) || (Tasks[TaskID] == 0)) - continue; - int StartTime = state->ActiveTasks[TaskIndex].AcceptedTime; - - SendActiveTaskDescription(c, TaskID, state->ActiveTasks[TaskIndex], StartTime, Tasks[TaskID]->Duration, - false); - Log(Logs::General, Logs::Tasks, "[UPDATE] SendActiveTasksToClient: Task %i, Activities: %i", TaskID, - GetActivityCount(TaskID)); - - int Sequence = 0; - int fixed_index = Tasks[TaskID]->type == TaskType::Task ? 0 : TaskIndex - 1; // hmmm fuck - for (int Activity = 0; Activity < GetActivityCount(TaskID); Activity++) { - if (c->GetTaskActivityState(Tasks[TaskID]->type, fixed_index, Activity) != ActivityHidden) { - Log(Logs::General, Logs::Tasks, "[UPDATE] Long: %i, %i, %i Complete=%i", TaskID, - Activity, fixed_index, TaskComplete); - if (Activity == GetActivityCount(TaskID) - 1) - SendTaskActivityLong(c, TaskID, Activity, fixed_index, - Tasks[TaskID]->Activity[Activity].Optional, TaskComplete); - else - SendTaskActivityLong(c, TaskID, Activity, fixed_index, - Tasks[TaskID]->Activity[Activity].Optional, 0); - } else { - Log(Logs::General, Logs::Tasks, "[UPDATE] Short: %i, %i, %i", TaskID, Activity, - fixed_index); - SendTaskActivityShort(c, TaskID, Activity, fixed_index); - } - Sequence++; - } - } -} - -void TaskManager::SendSingleActiveTaskToClient(Client *c, ClientTaskInformation &task_info, bool TaskComplete, - bool BringUpTaskJournal) -{ - int TaskID = task_info.TaskID; - - if (TaskID == 0 || Tasks[TaskID] == nullptr) - return; - - int StartTime = task_info.AcceptedTime; - SendActiveTaskDescription(c, TaskID, task_info, StartTime, Tasks[TaskID]->Duration, BringUpTaskJournal); - Log(Logs::General, Logs::Tasks, "[UPDATE] SendSingleActiveTasksToClient: Task %i, Activities: %i", TaskID, GetActivityCount(TaskID)); - - for (int Activity = 0; Activity < GetActivityCount(TaskID); Activity++) { - if(task_info.Activity[Activity].State != ActivityHidden) { - Log(Logs::General, Logs::Tasks, "[UPDATE] Long: %i, %i Complete=%i", TaskID, Activity, TaskComplete); - if (Activity == GetActivityCount(TaskID) - 1) - SendTaskActivityLong(c, TaskID, Activity, task_info.slot, - Tasks[TaskID]->Activity[Activity].Optional, TaskComplete); - else - SendTaskActivityLong(c, TaskID, Activity, task_info.slot, - Tasks[TaskID]->Activity[Activity].Optional, 0); - } else { - Log(Logs::General, Logs::Tasks, "[UPDATE] Short: %i, %i", TaskID, Activity); - SendTaskActivityShort(c, TaskID, Activity, task_info.slot); - } - } -} - -void TaskManager::SendActiveTaskDescription(Client *c, int TaskID, ClientTaskInformation &task_info, int StartTime, int Duration, bool BringUpTaskJournal) -{ - if ((TaskID < 1) || (TaskID >= MAXTASKS) || !Tasks[TaskID]) - return; - - int PacketLength = sizeof(TaskDescriptionHeader_Struct) + Tasks[TaskID]->Title.length() + 1 - + sizeof(TaskDescriptionData1_Struct) + Tasks[TaskID]->Description.length() + 1 - + sizeof(TaskDescriptionData2_Struct) + 1 + sizeof(TaskDescriptionTrailer_Struct); - - // If there is an item make the Reward text into a link to the item (only the first item if a list - // is specified). I have been unable to get multiple item links to work. - // - if(Tasks[TaskID]->RewardID && Tasks[TaskID]->item_link.empty()) { - int ItemID = 0; - // If the reward is a list of items, and the first entry on the list is valid - if (Tasks[TaskID]->RewardMethod == METHODSINGLEID) { - ItemID = Tasks[TaskID]->RewardID; - } else if (Tasks[TaskID]->RewardMethod == METHODLIST) { - ItemID = GoalListManager.GetFirstEntry(Tasks[TaskID]->RewardID); - if (ItemID < 0) - ItemID = 0; - } - - if(ItemID) { - const EQ::ItemData* reward_item = database.GetItem(ItemID); - - EQ::SayLinkEngine linker; - linker.SetLinkType(EQ::saylink::SayLinkItemData); - linker.SetItemData(reward_item); - linker.SetTaskUse(); - Tasks[TaskID]->item_link = linker.GenerateLink(); - } - } - - PacketLength += Tasks[TaskID]->Reward.length() + 1 + Tasks[TaskID]->item_link.length() + 1; - - char *Ptr; - TaskDescriptionHeader_Struct* tdh; - TaskDescriptionData1_Struct* tdd1; - TaskDescriptionData2_Struct* tdd2; - TaskDescriptionTrailer_Struct* tdt; - - auto outapp = new EQApplicationPacket(OP_TaskDescription, PacketLength); - - tdh = (TaskDescriptionHeader_Struct*)outapp->pBuffer; - - tdh->SequenceNumber = task_info.slot; - tdh->TaskID = TaskID; - tdh->open_window = BringUpTaskJournal; - tdh->task_type = static_cast(Tasks[TaskID]->type); - tdh->reward_type = 0; // TODO: 4 says Radiant Crystals else Ebon Crystals when shared task - - Ptr = (char *) tdh + sizeof(TaskDescriptionHeader_Struct); - - sprintf(Ptr, "%s", Tasks[TaskID]->Title.c_str()); - Ptr += Tasks[TaskID]->Title.length() + 1; - - tdd1 = (TaskDescriptionData1_Struct*)Ptr; - - tdd1->Duration = Duration; - tdd1->dur_code = static_cast(Tasks[TaskID]->dur_code); - - tdd1->StartTime = StartTime; - - Ptr = (char *) tdd1 + sizeof(TaskDescriptionData1_Struct); - - sprintf(Ptr, "%s", Tasks[TaskID]->Description.c_str()); - Ptr += Tasks[TaskID]->Description.length() + 1; - - tdd2 = (TaskDescriptionData2_Struct*)Ptr; - - // we have this reward stuff! - // if we ever don't hardcode this, TaskDescriptionTrailer_Struct will need to be fixed since - // "has_reward_selection" is after this bool! Smaller packet when this is 0 - tdd2->has_rewards = 1; - - tdd2->coin_reward = Tasks[TaskID]->CashReward; - tdd2->xp_reward = Tasks[TaskID]->XPReward ? 1 : 0; // just booled - tdd2->faction_reward = Tasks[TaskID]->faction_reward ? 1 : 0; // faction booled - - Ptr = (char *) tdd2 + sizeof(TaskDescriptionData2_Struct); - - // we actually have 2 strings here. One is max length 96 and not parsed for item links - // We actually skipped past that string incorrectly before, so TODO: fix item link string - sprintf(Ptr, "%s", Tasks[TaskID]->Reward.c_str()); - Ptr += Tasks[TaskID]->Reward.length() + 1; - - // second string is parsed for item links - sprintf(Ptr, "%s", Tasks[TaskID]->item_link.c_str()); - Ptr += Tasks[TaskID]->item_link.length() + 1; - - tdt = (TaskDescriptionTrailer_Struct*)Ptr; - tdt->Points = 0x00000000; // Points Count TODO: this does have a visible affect on the client ... - tdt->has_reward_selection = 0; // TODO: new rewards window - - c->QueuePacket(outapp); - safe_delete(outapp); -} - -bool ClientTaskState::IsTaskActivityCompleted(TaskType type, int index, int ActivityID) -{ - switch (type) { - case TaskType::Task: - if (index != 0) - return false; - return ActiveTask.Activity[ActivityID].State == ActivityCompleted; - case TaskType::Shared: - return false; // TODO: shared tasks - case TaskType::Quest: - if (index < MAXACTIVEQUESTS) - return ActiveQuests[index].Activity[ActivityID].State == ActivityCompleted; - default: - return false; - } - -} - -// should we be defaulting to hidden? -ActivityState ClientTaskState::GetTaskActivityState(TaskType type, int index, int ActivityID) -{ - switch (type) { - case TaskType::Task: - if (index != 0) - return ActivityHidden; - return ActiveTask.Activity[ActivityID].State; - case TaskType::Shared: - return ActivityHidden; // TODO: shared tasks - case TaskType::Quest: - if (index < MAXACTIVEQUESTS) - return ActiveQuests[index].Activity[ActivityID].State; - default: - return ActivityHidden; - } -} - -int ClientTaskState::GetTaskActivityDoneCount(TaskType type, int index, int ActivityID) -{ - switch (type) { - case TaskType::Task: - if (index != 0) - return 0; - return ActiveTask.Activity[ActivityID].DoneCount; - case TaskType::Shared: - return 0; // TODO: shared tasks - case TaskType::Quest: - if (index < MAXACTIVEQUESTS) - return ActiveQuests[index].Activity[ActivityID].DoneCount; - default: - return 0; - } -} - -int ClientTaskState::GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID) -{ - if (ActiveTask.TaskID == TaskID) - return ActiveTask.Activity[ActivityID].DoneCount; - - // TODO: shared tasks - - int ActiveTaskIndex = -1; - for(int i=0; ipBuffer; - cts->SequenceNumber = SequenceNumber; - cts->type = static_cast(type); - - Log(Logs::General, Logs::Tasks, "[UPDATE] CancelTask"); - - c->QueuePacket(outapp); - safe_delete(outapp); - - if(RemoveFromDB) - RemoveTask(c, SequenceNumber, type); -} - -void ClientTaskState::RemoveTask(Client *c, int sequenceNumber, TaskType type) -{ - int characterID = c->CharacterID(); - Log(Logs::General, Logs::Tasks, "[UPDATE] ClientTaskState Cancel Task %i ", sequenceNumber); - - int task_id = -1; - switch (type) { - case TaskType::Task: - if (sequenceNumber == 0) - task_id = ActiveTask.TaskID; - break; - case TaskType::Quest: - if (sequenceNumber < MAXACTIVEQUESTS) - task_id = ActiveQuests[sequenceNumber].TaskID; - break; - case TaskType::Shared: // TODO: - default: - break; - } - - std::string query = StringFormat("DELETE FROM character_activities WHERE charid=%i AND taskid = %i", - characterID, task_id); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - LogError("[TASKS] Error in CientTaskState::CancelTask [{}]", - results.ErrorMessage().c_str()); - return; - } - Log(Logs::General, Logs::Tasks, "[UPDATE] CancelTask: %s", query.c_str()); - - query = StringFormat("DELETE FROM character_tasks WHERE charid=%i AND taskid = %i AND type=%i", characterID, - task_id, static_cast(type)); - results = database.QueryDatabase(query); - if (!results.Success()) - LogError("[TASKS] Error in CientTaskState::CancelTask [{}]", - results.ErrorMessage().c_str()); - - Log(Logs::General, Logs::Tasks, "[UPDATE] CancelTask: %s", query.c_str()); - - switch (type) { - case TaskType::Task: - ActiveTask.TaskID = TASKSLOTEMPTY; - break; - case TaskType::Shared: - break; // TODO: shared tasks - case TaskType::Quest: - ActiveQuests[sequenceNumber].TaskID = TASKSLOTEMPTY; - ActiveTaskCount--; - break; - default: - break; - } -} - -void ClientTaskState::RemoveTaskByTaskID(Client *c, uint32 task_id) -{ - auto task_type = taskmanager->GetTaskType(task_id); - int character_id = c->CharacterID(); - Log(Logs::General, Logs::Tasks, "[UPDATE] RemoveTaskByTaskID: %d", task_id); - std::string query = fmt::format("DELETE FROM character_activities WHERE charid = {} AND taskid = {}", character_id, task_id); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - LogError("[TASKS] Error in CientTaskState::RemoveTaskByTaskID [{}]", results.ErrorMessage().c_str()); - return; - } - LogTasks("[UPDATE] RemoveTaskByTaskID: {}", query.c_str()); - - query = fmt::format("DELETE FROM character_tasks WHERE charid = {} AND taskid = {} AND type = {}", character_id, task_id, (int) task_type); - results = database.QueryDatabase(query); - if (!results.Success()) { - LogError("[TASKS] Error in ClientTaskState::RemoveTaskByTaskID [{}]", results.ErrorMessage().c_str()); - } - - LogTasks("[UPDATE] RemoveTaskByTaskID: {}", query.c_str()); - - switch (task_type) { - case TaskType::Task: - { - if (ActiveTask.TaskID == task_id) { - auto outapp = new EQApplicationPacket(OP_CancelTask, sizeof(CancelTask_Struct)); - CancelTask_Struct* cts = (CancelTask_Struct*)outapp->pBuffer; - cts->SequenceNumber = 0; - cts->type = static_cast(task_type); - LogTasks("[UPDATE] RemoveTaskByTaskID found Task [{}]", task_id); - c->QueuePacket(outapp); - safe_delete(outapp); - ActiveTask.TaskID = TASKSLOTEMPTY; - } - break; - } - case TaskType::Shared: - { - break; // TODO: shared tasks - } - case TaskType::Quest: - { - for (int active_quest = 0; active_quest < MAXACTIVEQUESTS; active_quest++) { - if (ActiveQuests[active_quest].TaskID == task_id) { - auto outapp = new EQApplicationPacket(OP_CancelTask, sizeof(CancelTask_Struct)); - CancelTask_Struct* cts = (CancelTask_Struct*)outapp->pBuffer; - cts->SequenceNumber = active_quest; - cts->type = static_cast(task_type); - LogTasks("[UPDATE] RemoveTaskByTaskID found Quest [{}] at index [{}]", task_id, active_quest); - ActiveQuests[active_quest].TaskID = TASKSLOTEMPTY; - ActiveTaskCount--; - c->QueuePacket(outapp); - safe_delete(outapp); - } - } - } - default: { - break; - } - } -} - -void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement) -{ - if (!taskmanager || TaskID < 0 || TaskID >= MAXTASKS) { - c->Message(Chat::Red, "Task system not functioning, or TaskID %i out of range.", TaskID); - return; - } - - auto task = taskmanager->Tasks[TaskID]; - - if (task == nullptr) { - c->Message(Chat::Red, "Invalid TaskID %i", TaskID); - return; - } - - bool max_tasks = false; - - switch (task->type) { - case TaskType::Task: - if (ActiveTask.TaskID != TASKSLOTEMPTY) - max_tasks = true; - break; - case TaskType::Shared: // TODO: shared tasks - // if (something) - max_tasks = true; - break; - case TaskType::Quest: - if (ActiveTaskCount == MAXACTIVEQUESTS) - max_tasks = true; - break; - default: - break; - } - - if (max_tasks) { - c->Message(Chat::Red, "You already have the maximum allowable number of active tasks (%i)", MAXACTIVEQUESTS); - return; - } - - // only Quests can have more than one, so don't need to check others - if (task->type == TaskType::Quest) { - for (int i = 0; i < MAXACTIVEQUESTS; i++) { - if (ActiveQuests[i].TaskID == TaskID) { - c->Message(Chat::Red, "You have already been assigned this task."); - return; - } - } - } - - if (enforce_level_requirement && !taskmanager->AppropriateLevel(TaskID, c->GetLevel())) { - c->Message(Chat::Red, "You are outside the level range of this task."); - return; - } - - if (!taskmanager->IsTaskRepeatable(TaskID) && IsTaskCompleted(TaskID)) - return; - - // We do it this way, because when the Client cancels a task, it retains the sequence number of the remaining - // tasks in it's window, until something causes the TaskDescription packets to be sent again. We could just - // resend all the active task data to the client when it cancels a task, but that could be construed as a - // waste of bandwidth. - // - ClientTaskInformation *active_slot = nullptr; - switch (task->type) { - case TaskType::Task: - active_slot = &ActiveTask; - break; - case TaskType::Shared: // TODO: shared - active_slot = nullptr; - break; - case TaskType::Quest: - for (int i = 0; i < MAXACTIVEQUESTS; i++) { - Log(Logs::General, Logs::Tasks, - "[UPDATE] ClientTaskState Looking for free slot in slot %i, found TaskID of %i", i, - ActiveQuests[i].TaskID); - if (ActiveQuests[i].TaskID == 0) { - active_slot = &ActiveQuests[i]; - break; - } - } - break; - default: - break; - } - - // This shouldn't happen unless there is a bug in the handling of ActiveTaskCount somewhere - if (active_slot == nullptr) { - c->Message(Chat::Red, "You already have the maximum allowable number of active tasks (%i)", MAXACTIVEQUESTS); - return; - } - - active_slot->TaskID = TaskID; - active_slot->AcceptedTime = time(nullptr); - active_slot->Updated = true; - active_slot->CurrentStep = -1; - - for (int i = 0; i < taskmanager->Tasks[TaskID]->ActivityCount; i++) { - active_slot->Activity[i].ActivityID = i; - active_slot->Activity[i].DoneCount = 0; - active_slot->Activity[i].State = ActivityHidden; - active_slot->Activity[i].Updated = true; - } - - UnlockActivities(c->CharacterID(), *active_slot); - - if (task->type == TaskType::Quest) - ActiveTaskCount++; - - taskmanager->SendSingleActiveTaskToClient(c, *active_slot, false, true); - c->Message(Chat::White, "You have been assigned the task '%s'.", taskmanager->Tasks[TaskID]->Title.c_str()); - taskmanager->SaveClientState(c, this); - std::string buf = std::to_string(TaskID); - - NPC *npc = entity_list.GetID(NPCID)->CastToNPC(); - if(npc) { - parse->EventNPC(EVENT_TASK_ACCEPTED, npc, c, buf.c_str(), 0); - } -} - -void ClientTaskState::ProcessTaskProximities(Client *c, float X, float Y, float Z) { - - float LastX = c->ProximityX(); - float LastY = c->ProximityY(); - float LastZ = c->ProximityZ(); - - if((LastX==X) && (LastY==Y) && (LastZ==Z)) return; - - Log(Logs::General, Logs::Tasks, "[PROXIMITY] Checking proximities for Position %8.3f, %8.3f, %8.3f", X, Y, Z); - int ExploreID = taskmanager->ProximityManager.CheckProximities(X, Y, Z); - - if(ExploreID > 0) { - Log(Logs::General, Logs::Tasks, "[PROXIMITY] Position %8.3f, %8.3f, %8.3f is within proximity %i", X, Y, Z, ExploreID); - UpdateTasksOnExplore(c, ExploreID); - } -} - -TaskGoalListManager::TaskGoalListManager() -{ - NumberOfLists = 0; -} - -TaskGoalListManager::~TaskGoalListManager() {} - -bool TaskGoalListManager::LoadLists() -{ - - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] TaskGoalListManager::LoadLists Called"); - - TaskGoalLists.clear(); - - const char *ERR_MYSQLERROR = "Error in TaskGoalListManager::LoadLists: %s %s"; - - NumberOfLists = 0; - - std::string query = "SELECT `listid`, COUNT(`entry`) " - "FROM `goallists` GROUP by `listid` " - "ORDER BY `listid`"; - auto results = content_db.QueryDatabase(query); - if (!results.Success()) { - return false; - } - - NumberOfLists = results.RowCount(); - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] Database returned a count of %i lists", NumberOfLists); - - TaskGoalLists.reserve(NumberOfLists); - - int list_index = 0; - - for (auto row = results.begin(); row != results.end(); ++row) { - int listID = atoi(row[0]); - int listSize = atoi(row[1]); - - TaskGoalLists.push_back({listID, 0, 0}); - - TaskGoalLists[list_index].GoalItemEntries.reserve(listSize); - - list_index++; - } - - auto goal_lists = GoallistsRepository::GetWhere(content_db, "TRUE ORDER BY listid, entry ASC"); - - for (list_index = 0; list_index < NumberOfLists; list_index++) { - - int list_id = TaskGoalLists[list_index].ListID; - - for (auto &entry: goal_lists) { - if (entry.listid == list_id) { - if (entry.entry < TaskGoalLists[list_index].Min) { - TaskGoalLists[list_index].Min = entry.entry; - } - - if (entry.entry > TaskGoalLists[list_index].Max) { - TaskGoalLists[list_index].Max = entry.entry; - } - - TaskGoalLists[list_index].GoalItemEntries.push_back(entry.entry); - - LogTasksDetail( - "Goal list index [{}] loading list [{}] entry [{}]", - list_index, - list_id, - entry.entry - ); - } - } - } - - return true; - -} - -int TaskGoalListManager::GetListByID(int ListID) { - - // Find the list with the specified ListID and return the index - auto it = std::find_if(TaskGoalLists.begin(), TaskGoalLists.end(), - [ListID](const TaskGoalList_Struct &t) { return t.ListID == ListID; }); - - if (it == TaskGoalLists.end()) - return -1; - - return std::distance(TaskGoalLists.begin(), it); -} - -int TaskGoalListManager::GetFirstEntry(int ListID) { - - int ListIndex = GetListByID(ListID); - - if((ListIndex < 0) || (ListIndex >= NumberOfLists)) return -1; - - if(TaskGoalLists[ListIndex].GoalItemEntries.empty()) return -1; - - return TaskGoalLists[ListIndex].GoalItemEntries[0]; -} - -std::vector TaskGoalListManager::GetListContents(int ListID) { - - std::vector ListContents; - - int ListIndex = GetListByID(ListID); - - if((ListIndex < 0) || (ListIndex >= NumberOfLists)) return ListContents; - - ListContents = TaskGoalLists[ListIndex].GoalItemEntries; - - return ListContents; - -} - -bool TaskGoalListManager::IsInList(int ListID, int Entry) -{ - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskGoalListManager::IsInList(%i, %i)", ListID, Entry); - - int ListIndex = GetListByID(ListID); - - if ((ListIndex < 0) || (ListIndex >= NumberOfLists)) - return false; - - if ((Entry < TaskGoalLists[ListIndex].Min) || (Entry > TaskGoalLists[ListIndex].Max)) - return false; - - int FirstEntry = 0; - auto &task = TaskGoalLists[ListIndex]; - - auto it = std::find(task.GoalItemEntries.begin(), task.GoalItemEntries.end(), Entry); - - if (it == task.GoalItemEntries.end()) - return false; - - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskGoalListManager::IsInList(%i, %i) returning true", ListIndex, - Entry); - return true; -} - -TaskProximityManager::TaskProximityManager() { - - -} - -TaskProximityManager::~TaskProximityManager() { - - -} - -bool TaskProximityManager::LoadProximities(int zoneID) { - TaskProximity proximity; - - Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] TaskProximityManager::LoadProximities Called for zone %i", zoneID); - TaskProximities.clear(); - - std::string query = StringFormat("SELECT `exploreid`, `minx`, `maxx`, " - "`miny`, `maxy`, `minz`, `maxz` " - "FROM `proximities` WHERE `zoneid` = %i " - "ORDER BY `zoneid` ASC", zoneID); - auto results = content_db.QueryDatabase(query); - if (!results.Success()) { - return false; - } - - for( auto row = results.begin(); row != results.end(); ++row) { - proximity.ExploreID = atoi(row[0]); - proximity.MinX = atof(row[1]); - proximity.MaxX = atof(row[2]); - proximity.MinY = atof(row[3]); - proximity.MaxY = atof(row[4]); - proximity.MinZ = atof(row[5]); - proximity.MaxZ = atof(row[6]); - - TaskProximities.push_back(proximity); - } - - return true; - -} - -int TaskProximityManager::CheckProximities(float X, float Y, float Z) { - - for(unsigned int i=0; iMinX, P->MaxX, P->MinY, P->MaxY, P->MinZ, P->MaxZ); - - if(X < P->MinX || X > P->MaxX || Y < P->MinY || Y > P->MaxY || - Z < P->MinZ || Z > P->MaxZ) continue; - - return P->ExploreID; - - } - - return 0; -} - diff --git a/zone/tasks.h b/zone/tasks.h index cb4cd63c1..d3fed2c09 100644 --- a/zone/tasks.h +++ b/zone/tasks.h @@ -1,27 +1,7 @@ -/* EQEMu: Everquest Server Emulator -Copyright (C) 2001-2004 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 TASKS_H #define TASKS_H #include "../common/types.h" - #include #include #include @@ -29,304 +9,141 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) #define MAXTASKS 10000 #define MAXTASKSETS 1000 -// The Client has a hard cap of 19 active quests, 29 in SoD+ -#define MAXACTIVEQUESTS 19 -// The Max Chooser (Task Selector entries) is capped at 40 in the Titanium Client. -#define MAXCHOOSERENTRIES 40 -// The Client has a hard cap of 20 activities per task. -#define MAXACTIVITIESPERTASK 20 -// This is used to determine if a client's active task slot is empty. -#define TASKSLOTEMPTY 0 +#define MAXACTIVEQUESTS 19 // The Client has a hard cap of 19 active quests, 29 in SoD+ +#define MAXCHOOSERENTRIES 40 // The Max Chooser (Task Selector entries) is capped at 40 in the Titanium Client. +#define MAXACTIVITIESPERTASK 20 // The Client has a hard cap of 20 activities per task. +#define TASKSLOTEMPTY 0 // This is used to determine if a client's active task slot is empty. // Command Codes for worldserver ServerOP_ReloadTasks -// -#define RELOADTASKS 0 -#define RELOADTASKGOALLISTS 1 -#define RELOADTASKPROXIMITIES 2 -#define RELOADTASKSETS 3 +#define RELOADTASKS 0 +#define RELOADTASKGOALLISTS 1 +#define RELOADTASKPROXIMITIES 2 +#define RELOADTASKSETS 3 class Client; class Mob; -namespace EQ -{ +namespace EQ { class ItemInstance; } -struct TaskGoalList_Struct { - int ListID; - int Min, Max; - std::vector GoalItemEntries; -}; - -// This is used for handling lists, loading them from the database, searching them. -// Used for lists of NPCs to kill, items to loot, etc, as well as lists of items to -// reward the player with on completion of the task. -// -class TaskGoalListManager { - -public: - TaskGoalListManager(); - ~TaskGoalListManager(); - bool LoadLists(); - int GetListByID(int ListID); - bool IsInList(int ListID, int Entry); - int GetFirstEntry(int ListID); - std::vector GetListContents(int ListIndex); - -private: - - std::vector TaskGoalLists; - int NumberOfLists; -}; - -typedef struct { - int ExploreID; - float MinX, MaxX, MinY, MaxY, MinZ, MaxZ; -} TaskProximity; - -// This class is used for managing proximities so that Quest NPC proximities don't need to be used. -class TaskProximityManager { - -public: - TaskProximityManager(); - ~TaskProximityManager(); - bool LoadProximities(int ZoneID); - int CheckProximities(float X, float Y, float Z); - -private: - std::vector TaskProximities; -}; - -typedef enum { METHODSINGLEID = 0, METHODLIST = 1, METHODQUEST = 2 } TaskMethodType; +typedef enum { + METHODSINGLEID = 0, + METHODLIST = 1, + METHODQUEST = 2 +} TaskMethodType; struct ActivityInformation { - int StepNumber; - int Type; - std::string target_name; // name mob, location -- default empty - std::string item_list; // likely defaults to empty - std::string skill_list; // IDs ; separated -- default -1 - std::string spell_list; // IDs ; separated -- default 0 - std::string desc_override; // overrides auto generated description -- default empty - int skill_id; // older clients, first id from above - int spell_id; // older clients, first id from above - int GoalID; - TaskMethodType GoalMethod; - int GoalCount; - int DeliverToNPC; - std::vector ZoneIDs; - std::string zones; // IDs ; searated, ZoneID is the first in this list for older clients -- default empty string - bool Optional; + int step_number; + int activity_type; + std::string target_name; // name mob, location -- default empty + std::string item_list; // likely defaults to empty + std::string skill_list; // IDs ; separated -- default -1 + std::string spell_list; // IDs ; separated -- default 0 + std::string description_override; // overrides auto generated description -- default empty + int skill_id; // older clients, first id from above + int spell_id; // older clients, first id from above + int goal_id; + TaskMethodType goal_method; + int goal_count; + int deliver_to_npc; + std::vector zone_ids; + std::string zones; // IDs ; searated, ZoneID is the first in this list for older clients -- default empty string + bool optional; - inline bool CheckZone(int zone_id) { - if (ZoneIDs.empty()) + inline bool CheckZone(int zone_id) + { + if (zone_ids.empty()) { return true; - return std::find(ZoneIDs.begin(), ZoneIDs.end(), zone_id) != ZoneIDs.end(); + } + return std::find(zone_ids.begin(), zone_ids.end(), zone_id) != zone_ids.end(); } }; -typedef enum { ActivitiesSequential = 0, ActivitiesStepped = 1 } SequenceType; +typedef enum { + ActivitiesSequential = 0, + ActivitiesStepped = 1 +} SequenceType; enum class TaskType { - Task = 0, // can have at max 1 - Shared = 1, // can have at max 1 - Quest = 2, // can have at max 19 or 29 depending on client - E = 3 // can have at max 19 or 29 depending on client, not present in live anymore + Task = 0, // can have at max 1 + Shared = 1, // can have at max 1 + Quest = 2, // can have at max 19 or 29 depending on client + E = 3 // can have at max 19 or 29 depending on client, not present in live anymore }; enum class DurationCode { - None = 0, - Short = 1, + None = 0, + Short = 1, Medium = 2, - Long = 3 + Long = 3 }; struct TaskInformation { - TaskType type; - int Duration; - DurationCode dur_code; // description for time investment for when Duration == 0 - std::string Title; // max length 64 - std::string Description; // max length 4000, 2048 on Tit - std::string Reward; - std::string item_link; // max length 128 older clients, item link gets own string - std::string completion_emote; // emote after completing task, yellow. Maybe should make more generic ... but yellow for now! - int RewardID; - int CashReward; // Expressed in copper - int XPReward; - int faction_reward; // just a npc_faction_id - TaskMethodType RewardMethod; - int ActivityCount; - SequenceType SequenceMode; - int LastStep; - short MinLevel; - short MaxLevel; - bool Repeatable; - ActivityInformation Activity[MAXACTIVITIESPERTASK]; + TaskType type; + int duration; + DurationCode duration_code; // description for time investment for when duration == 0 + std::string title; // max length 64 + std::string description; // max length 4000, 2048 on Tit + std::string reward; + std::string item_link; // max length 128 older clients, item link gets own string + std::string completion_emote; // emote after completing task, yellow. Maybe should make more generic ... but yellow for now! + int reward_id; + int cash_reward; // Expressed in copper + int experience_reward; + int faction_reward; // just a npc_faction_id + TaskMethodType reward_method; + int activity_count; + SequenceType sequence_mode; + int last_step; + short min_level; + short max_level; + bool repeatable; + ActivityInformation activity_information[MAXACTIVITIESPERTASK]; }; -typedef enum { ActivityHidden = 0, ActivityActive = 1, ActivityCompleted = 2 } ActivityState; - -typedef enum { ActivityDeliver = 1, ActivityKill = 2, ActivityLoot = 3, ActivitySpeakWith = 4, ActivityExplore = 5, - ActivityTradeSkill = 6, ActivityFish = 7, ActivityForage = 8, ActivityCastOn = 9, ActivitySkillOn = 10, - ActivityTouch = 11, ActivityCollect = 13, ActivityGiveCash = 100 } ActivityType; +typedef enum { + ActivityHidden = 0, + ActivityActive = 1, + ActivityCompleted = 2 +} ActivityState; +typedef enum { + ActivityDeliver = 1, + ActivityKill = 2, + ActivityLoot = 3, + ActivitySpeakWith = 4, + ActivityExplore = 5, + ActivityTradeSkill = 6, + ActivityFish = 7, + ActivityForage = 8, + ActivityCastOn = 9, + ActivitySkillOn = 10, + ActivityTouch = 11, + ActivityCollect = 13, + ActivityGiveCash = 100 +} ActivityType; struct ClientActivityInformation { - int ActivityID; - int DoneCount; - ActivityState State; - bool Updated; // Flag so we know if we need to update the database + int activity_id; + int done_count; + ActivityState activity_state; + bool updated; // Flag so we know if we need to updated the database }; struct ClientTaskInformation { - int slot; // intrusive, but makes things easier :P - int TaskID; - int CurrentStep; - int AcceptedTime; - bool Updated; - ClientActivityInformation Activity[MAXACTIVITIESPERTASK]; + int slot; // intrusive, but makes things easier :P + int task_id; + int current_step; + int accepted_time; + bool updated; + ClientActivityInformation activity[MAXACTIVITIESPERTASK]; }; struct CompletedTaskInformation { - int TaskID; - int CompletedTime; - bool ActivityDone[MAXACTIVITIESPERTASK]; -}; - -class ClientTaskState { - -public: - ClientTaskState(); - ~ClientTaskState(); - void ShowClientTasks(Client *c); - inline int GetActiveTaskCount() { return ActiveTaskCount; } - int GetActiveTaskID(int index); - bool IsTaskActivityCompleted(TaskType type, int index, int ActivityID); - int GetTaskActivityDoneCount(TaskType type, int index, int ActivityID); - int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID); - int GetTaskStartTime(TaskType type, int index); - void AcceptNewTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false); - void FailTask(Client *c, int TaskID); - int TaskTimeLeft(int TaskID); - int IsTaskCompleted(int TaskID); - bool IsTaskActive(int TaskID); - bool IsTaskActivityActive(int TaskID, int ActivityID); - ActivityState GetTaskActivityState(TaskType type, int index, int ActivityID); - void UpdateTaskActivity(Client *c, int TaskID, int ActivityID, int Count, bool ignore_quest_update = false); - void ResetTaskActivity(Client *c, int TaskID, int ActivityID); - void CancelTask(Client *c, int SequenceNumber, TaskType type, bool RemoveFromDB = true); - void CancelAllTasks(Client *c); - void RemoveTask(Client *c, int SequenceNumber, TaskType type); - void RemoveTaskByTaskID(Client *c, uint32 task_id); - bool UpdateTasksByNPC(Client *c, int ActivityType, int NPCTypeID); - void UpdateTasksOnKill(Client *c, int NPCTypeID); - void UpdateTasksForItem(Client *c, ActivityType Type, int ItemID, int Count=1); - void UpdateTasksOnExplore(Client *c, int ExploreID); - bool UpdateTasksOnSpeakWith(Client *c, int NPCTypeID); - bool UpdateTasksOnDeliver(Client *c, std::list& Items, int Cash, int NPCTypeID); - void UpdateTasksOnTouch(Client *c, int ZoneID); - void ProcessTaskProximities(Client *c, float X, float Y, float Z); - bool TaskOutOfTime(TaskType type, int Index); - void TaskPeriodicChecks(Client *c); - void SendTaskHistory(Client *c, int TaskIndex); - void RewardTask(Client *c, TaskInformation *Task); - void EnableTask(int CharID, int TaskCount, int *TaskList); - void DisableTask(int CharID, int TaskCount, int *TaskList); - bool IsTaskEnabled(int TaskID); - int EnabledTaskCount(int TaskSetID); - int ActiveSpeakTask(int NPCID); - int ActiveSpeakActivity(int NPCID, int TaskID); - int ActiveTasksInSet(int TaskSetID); - int CompletedTasksInSet(int TaskSetID); - bool HasSlotForTask(TaskInformation *task); - - inline bool HasFreeTaskSlot() { return ActiveTask.TaskID == TASKSLOTEMPTY; } - - friend class TaskManager; - -private: - bool UnlockActivities(int CharID, ClientTaskInformation &task_info); - void IncrementDoneCount(Client *c, TaskInformation *Task, int TaskIndex, int ActivityID, int Count = 1, bool ignore_quest_update = false); - inline ClientTaskInformation *GetClientTaskInfo(TaskType type, int index) - { - ClientTaskInformation *info = nullptr; - switch (type) { - case TaskType::Task: - if (index == 0) - info = &ActiveTask; - break; - case TaskType::Shared: - break; - case TaskType::Quest: - if (index < MAXACTIVEQUESTS) - info = &ActiveQuests[index]; - break; - default: - break; - } - return info; - } - int ActiveTaskCount; - union { // easier to loop over - struct { - ClientTaskInformation ActiveTask; // only one - ClientTaskInformation ActiveQuests[MAXACTIVEQUESTS]; - }; - ClientTaskInformation ActiveTasks[MAXACTIVEQUESTS + 1]; - }; - // Shared tasks should be limited to 1 as well - std::vector EnabledTasks; - std::vector CompletedTasks; - int LastCompletedTaskLoaded; - bool CheckedTouchActivities; -}; - - -class TaskManager { - -public: - TaskManager(); - ~TaskManager(); - int GetActivityCount(int TaskID); - bool LoadSingleTask(int TaskID); - bool LoadTasks(int SingleTask=0); - void ReloadGoalLists(); - inline void LoadProximities(int ZoneID) { ProximityManager.LoadProximities(ZoneID); } - bool LoadTaskSets(); - bool LoadClientState(Client *c, ClientTaskState *state); - bool SaveClientState(Client *c, ClientTaskState *state); - void SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *TaskList); - void SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *TaskList); - bool AppropriateLevel(int TaskID, int PlayerLevel); - int GetTaskMinLevel(int TaskID); - int GetTaskMaxLevel(int TaskID); - std::string GetTaskName(uint32 task_id); - TaskType GetTaskType(uint32 task_id); - void TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID); - void TaskQuestSetSelector(Client *c, ClientTaskState *state, Mob *mob, int count, int *tasks); // task list provided by QuestManager (perl/lua) - void SendActiveTasksToClient(Client *c, bool TaskComplete=false); - void SendSingleActiveTaskToClient(Client *c, ClientTaskInformation &task_info, bool TaskComplete, bool BringUpTaskJournal = false); - void SendTaskActivityShort(Client *c, int TaskID, int ActivityID, int ClientTaskIndex); - void SendTaskActivityLong(Client *c, int TaskID, int ActivityID, int ClientTaskIndex, - bool Optional, bool TaskComplete=false); - void SendTaskActivityNew(Client *c, int TaskID, int ActivityID, int ClientTaskIndex, - bool Optional, bool TaskComplete=false); - void SendCompletedTasksToClient(Client *c, ClientTaskState *state); - void ExplainTask(Client *c, int TaskID); - int FirstTaskInSet(int TaskSet); - int LastTaskInSet(int TaskSet); - int NextTaskInSet(int TaskSet, int TaskID); - bool IsTaskRepeatable(int TaskID); - friend class ClientTaskState; - - -private: - TaskGoalListManager GoalListManager; - TaskProximityManager ProximityManager; - TaskInformation* Tasks[MAXTASKS]; - std::vector TaskSets[MAXTASKSETS]; - void SendActiveTaskDescription(Client *c, int TaskID, ClientTaskInformation &task_info, int StartTime, int Duration, bool BringUpTaskJournal=false); - + int task_id; + int completed_time; + bool activity_done[MAXACTIVITIESPERTASK]; }; #endif diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index eea45d057..76b00398e 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -2455,7 +2455,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) CZTaskDisablePlayer_Struct* CZUA = (CZTaskDisablePlayer_Struct*) pack->pBuffer; auto client = entity_list.GetClientByCharID(CZUA->character_id); if (client) { - client->DisableTask(1, (int*) CZUA->task_id); + client->DisableTask(1, reinterpret_cast(CZUA->task_id)); } break; } @@ -2467,7 +2467,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) for (int member_index = 0; member_index < MAX_GROUP_MEMBERS; member_index++) { if (client_group->members[member_index] && client_group->members[member_index]->IsClient()) { auto group_member = client_group->members[member_index]->CastToClient(); - group_member->DisableTask(1, (int*) CZUA->task_id); + group_member->DisableTask(1, reinterpret_cast(CZUA->task_id)); } } } @@ -2481,7 +2481,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) for (int member_index = 0; member_index < MAX_RAID_MEMBERS; member_index++) { if (client_raid->members[member_index].member && client_raid->members[member_index].member->IsClient()) { auto raid_member = client_raid->members[member_index].member->CastToClient(); - raid_member->DisableTask(1, (int*) CZUA->task_id); + raid_member->DisableTask(1, reinterpret_cast(CZUA->task_id)); } } } @@ -2492,7 +2492,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) CZTaskDisableGuild_Struct* CZUA = (CZTaskDisableGuild_Struct*) pack->pBuffer; for (auto &client : entity_list.GetClientList()) { if (client.second->GuildID() > 0 && client.second->GuildID() == CZUA->guild_id) { - client.second->DisableTask(1, (int*) CZUA->task_id); + client.second->DisableTask(1, reinterpret_cast(CZUA->task_id)); } } break; @@ -2502,7 +2502,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) CZTaskEnablePlayer_Struct* CZUA = (CZTaskEnablePlayer_Struct*) pack->pBuffer; auto client = entity_list.GetClientByCharID(CZUA->character_id); if (client) { - client->EnableTask(1, (int*) CZUA->task_id); + client->EnableTask(1, reinterpret_cast(CZUA->task_id)); } break; } @@ -2514,7 +2514,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) for (int member_index = 0; member_index < MAX_GROUP_MEMBERS; member_index++) { if (client_group->members[member_index] && client_group->members[member_index]->IsClient()) { auto group_member = client_group->members[member_index]->CastToClient(); - group_member->EnableTask(1, (int*) CZUA->task_id); + group_member->EnableTask(1, reinterpret_cast(CZUA->task_id)); } } } @@ -2528,7 +2528,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) for (int member_index = 0; member_index < MAX_RAID_MEMBERS; member_index++) { if (client_raid->members[member_index].member && client_raid->members[member_index].member->IsClient()) { auto raid_member = client_raid->members[member_index].member->CastToClient(); - raid_member->EnableTask(1, (int*) CZUA->task_id); + raid_member->EnableTask(1, reinterpret_cast(CZUA->task_id)); } } } @@ -2539,7 +2539,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) CZTaskEnableGuild_Struct* CZUA = (CZTaskEnableGuild_Struct*) pack->pBuffer; for (auto &client : entity_list.GetClientList()) { if (client.second->GuildID() > 0 && client.second->GuildID() == CZUA->guild_id) { - client.second->EnableTask(1, (int*) CZUA->task_id); + client.second->EnableTask(1, reinterpret_cast(CZUA->task_id)); } } break; @@ -2666,7 +2666,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) for (auto &client : entity_list.GetClientList()) { auto client_status = client.second->Admin(); if (client_status >= WWDT->min_status && (client_status <= WWDT->max_status || WWDT->max_status == 0)) { - client.second->DisableTask(1, (int *) WWDT->task_id); + client.second->DisableTask(1, reinterpret_cast(WWDT->task_id)); } } break; @@ -2677,7 +2677,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) for (auto &client : entity_list.GetClientList()) { auto client_status = client.second->Admin(); if (client_status >= WWET->min_status && (client_status <= WWET->max_status || WWET->max_status == 0)) { - client.second->EnableTask(1, (int *) WWET->task_id); + client.second->EnableTask(1, reinterpret_cast(WWET->task_id)); } } break; @@ -3100,16 +3100,16 @@ void WorldServer::HandleReloadTasks(ServerPacket *pack) if (rts->Parameter == 0) { Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] Reload ALL tasks"); - safe_delete(taskmanager); - taskmanager = new TaskManager; - taskmanager->LoadTasks(); + safe_delete(task_manager); + task_manager = new TaskManager; + task_manager->LoadTasks(); if (zone) - taskmanager->LoadProximities(zone->GetZoneID()); + task_manager->LoadProximities(zone->GetZoneID()); entity_list.ReloadAllClientsTaskState(); } else { Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] Reload only task %i", rts->Parameter); - taskmanager->LoadTasks(rts->Parameter); + task_manager->LoadTasks(rts->Parameter); entity_list.ReloadAllClientsTaskState(rts->Parameter); } @@ -3118,18 +3118,18 @@ void WorldServer::HandleReloadTasks(ServerPacket *pack) case RELOADTASKPROXIMITIES: if (zone) { Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] Reload task proximities"); - taskmanager->LoadProximities(zone->GetZoneID()); + task_manager->LoadProximities(zone->GetZoneID()); } break; case RELOADTASKGOALLISTS: Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] Reload task goal lists"); - taskmanager->ReloadGoalLists(); + task_manager->ReloadGoalLists(); break; case RELOADTASKSETS: Log(Logs::General, Logs::Tasks, "[GLOBALLOAD] Reload task sets"); - taskmanager->LoadTaskSets(); + task_manager->LoadTaskSets(); break; default: diff --git a/zone/zone.cpp b/zone/zone.cpp index 57f886eec..2e29e8eec 100755 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -964,7 +964,7 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) lootvar = 0; if(RuleB(TaskSystem, EnableTaskSystem)) { - taskmanager->LoadProximities(zoneid); + task_manager->LoadProximities(zoneid); } short_name = strcpy(new char[strlen(in_short_name)+1], in_short_name);