From a6d5df5be52a6cb29992c3c27895603bda745491 Mon Sep 17 00:00:00 2001 From: typedeck0 <113395677+typedeck0@users.noreply.github.com> Date: Wed, 21 Aug 2024 20:28:29 -0400 Subject: [PATCH] Update know_thy_enemy.cpp --- know_thy_enemy.cpp | 719 +++++++++++++++------------------------------ 1 file changed, 230 insertions(+), 489 deletions(-) diff --git a/know_thy_enemy.cpp b/know_thy_enemy.cpp index f11e04b..cf5d316 100644 --- a/know_thy_enemy.cpp +++ b/know_thy_enemy.cpp @@ -8,185 +8,16 @@ #include #include #include +#include #include #include -/* combat state change */ -enum cbtstatechange { - CBTS_NONE, // not used - not this kind of event - CBTS_ENTERCOMBAT, // src_agent entered combat, dst_agent is subgroup - CBTS_EXITCOMBAT, // src_agent left combat - CBTS_CHANGEUP, // src_agent is now alive - CBTS_CHANGEDEAD, // src_agent is now dead - CBTS_CHANGEDOWN, // src_agent is now downed - CBTS_SPAWN, // src_agent is now in game tracking range (not in realtime api) - CBTS_DESPAWN, // src_agent is no longer being tracked (not in realtime api) - CBTS_HEALTHUPDATE, // src_agent is at health percent. dst_agent = percent * 10000 (eg. 99.5% will be 9950) (not in realtime api) - CBTS_LOGSTART, // log start. value = server unix timestamp **uint32**. buff_dmg = local unix timestamp - CBTS_LOGEND, // log end. value = server unix timestamp **uint32**. buff_dmg = local unix timestamp - CBTS_WEAPSWAP, // src_agent swapped weapon set. dst_agent = current set id (0/1 water, 4/5 land) - CBTS_MAXHEALTHUPDATE, // src_agent has had it's maximum health changed. dst_agent = new max health (not in realtime api) - CBTS_POINTOFVIEW, // src_agent is agent of "recording" player (not in realtime api) - CBTS_LANGUAGE, // src_agent is text language (not in realtime api) - CBTS_GWBUILD, // src_agent is game build (not in realtime api) - CBTS_SHARDID, // src_agent is sever shard id (not in realtime api) - CBTS_REWARD, // src_agent is self, dst_agent is reward id, value is reward type. these are the wiggly boxes that you get - CBTS_BUFFINITIAL, // combat event that will appear once per buff per agent on logging start (statechange==18, buff==18, normal cbtevent otherwise) - CBTS_POSITION, // src_agent changed, cast float* p = (float*)&dst_agent, access as x/y/z (float[3]) (not in realtime api) - CBTS_VELOCITY, // src_agent changed, cast float* v = (float*)&dst_agent, access as x/y/z (float[3]) (not in realtime api) - CBTS_FACING, // src_agent changed, cast float* f = (float*)&dst_agent, access as x/y (float[2]) (not in realtime api) - CBTS_TEAMCHANGE, // src_agent change, dst_agent new team id - CBTS_ATTACKTARGET, // src_agent is an attacktarget, dst_agent is the parent agent (gadget type), value is the current targetable state (not in realtime api) - CBTS_TARGETABLE, // dst_agent is new target-able state (0 = no, 1 = yes. default yes) (not in realtime api) - CBTS_MAPID, // src_agent is map id (not in realtime api) - CBTS_REPLINFO, // internal use, won't see anywhere - CBTS_STACKACTIVE, // src_agent is agent with buff, dst_agent is the stackid marked active - CBTS_STACKRESET, // src_agent is agent with buff, value is the duration to reset to (also marks inactive), pad61-pad64 buff instance id - CBTS_GUILD, // src_agent is agent, dst_agent through buff_dmg is 16 byte guid (client form, needs minor rearrange for api form) - CBTS_BUFFINFO, // is_flanking = probably invuln, is_shields = probably invert, is_offcycle = category, pad61 = stacking type, pad62 = probably resistance, src_master_instid = max stacks, overstack_value = duration cap (not in realtime) - CBTS_BUFFFORMULA, // (float*)&time[8]: type attr1 attr2 param1 param2 param3 trait_src trait_self, (float*)&src_instid[2] = buff_src buff_self, is_flanking = !npc, is_shields = !player, is_offcycle = break, overstack = value of type determined by pad61 (none/number/skill) (not in realtime, one per formula) - CBTS_SKILLINFO, // (float*)&time[4]: recharge range0 range1 tooltiptime (not in realtime) - CBTS_SKILLTIMING, // src_agent = action, dst_agent = at millisecond (not in realtime, one per timing) - CBTS_BREAKBARSTATE, // src_agent is agent, value is u16 game enum (active, recover, immune, none) (not in realtime api) - CBTS_BREAKBARPERCENT, // src_agent is agent, value is float with percent (not in realtime api) - CBTS_ERROR, // (char*)&time[32]: error string (not in realtime api) - CBTS_TAG, // src_agent is agent, value is the id (volatile, game build dependent) of the tag, buff will be non-zero if commander - CBTS_BARRIERUPDATE, // src_agent is at barrier percent. dst_agent = percent * 10000 (eg. 99.5% will be 9950) (not in realtime api) - CBTS_STATRESET, // with arc ui stats reset (not in log), src_agent = npc id of active log - CBTS_EXTENSION, // cbtevent with statechange byte set to this - CBTS_APIDELAYED, // cbtevent with statechange byte set to this - CBTS_INSTANCESTART, // src_agent is ms time at which the instance likely was started - CBTS_TICKRATE, // every 500ms, src_agent = 25 - tickrate (when tickrate < 21) - CBTS_LAST90BEFOREDOWN, // src_agent is enemy agent that went down, dst_agent is time in ms since last 90% (for downs contribution) - CBTS_EFFECT, // retired, not used since 230716+ - CBTS_IDTOGUID, // &src_agent = 16byte persistent content guid, overstack_value is of contentlocal enum, skillid is content id (not in realtime api) - CBTS_LOGNPCUPDATE, // log npc update. value = server unix timestamp **uint32**. buff_dmg = local unix timestamp. src_agent = species id. dst_agent = agent, flanking = is gadget - CBTS_IDLEEVENT, // internal use, won't see anywhere - CBTS_EXTENSIONCOMBAT, // cbtevent with statechange byte set to this, treats skillid as skill for evtc skill table - CBTS_FRACTALSCALE, // src_agent = fractal scale - CBTS_EFFECT2, // src_agent is owner. dst_agent if at agent, else &value = float[3] xyz. &iff = uint32 duraation. &buffremove = uint32 trackable id. &is_shields = int16[3] orientation, values are original*1000 clamped to int16 (not in realtime api) - CBTS_UNKNOWN -}; - -/* is friend/foe */ -enum iff { - IFF_FRIEND, - IFF_FOE, - IFF_UNKNOWN -}; - -/* arcdps export table */ -struct arcdps_exports { - uintptr_t size; /* size of exports table */ - uint32_t sig; /* pick a number between 0 and uint32_t max that isn't used by other modules */ - uint32_t imguivers; /* set this to IMGUI_VERSION_NUM. if you don't use imgui, 18000 (as of 2021-02-02) */ - const char* out_name; /* name string */ - const char* out_build; /* build string */ - void* wnd_nofilter; /* wndproc callback, fn(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam), return assigned to umsg */ - void* combat; /* combat event callback, fn(cbtevent* ev, ag* src, ag* dst, char* skillname, uint64_t id, uint64_t revision) */ - void* imgui; /* ::present callback, before imgui::render, fn(uint32_t not_charsel_or_loading, uint32_t hide_if_combat_or_ooc) */ - void* options_end; /* ::present callback, appending to the end of options window in arcdps, fn() */ - void* combat_local; /* combat event callback like area but from chat log, fn(cbtevent* ev, ag* src, ag* dst, char* skillname, uint64_t id, uint64_t revision) */ - void* wnd_filter; /* wndproc callback like wnd_nofilter above, input filered using modifiers */ - void* options_windows; /* called once per 'window' option checkbox, with null at the end, non-zero return disables arcdps drawing that checkbox, fn(char* windowname) */ -}; - -/* combat event - see evtc docs for details, revision param in combat cb is equivalent of revision byte header */ -typedef struct cbtevent { - uint64_t time; - uint64_t src_agent; - uint64_t dst_agent; - int32_t value; - int32_t buff_dmg; - uint32_t overstack_value; - uint32_t skillid; - uint16_t src_instid; - uint16_t dst_instid; - uint16_t src_master_instid; - uint16_t dst_master_instid; - uint8_t iff; - uint8_t buff; - uint8_t result; - uint8_t is_activation; - uint8_t is_buffremove; - uint8_t is_ninety; - uint8_t is_fifty; - uint8_t is_moving; - uint8_t is_statechange; - uint8_t is_flanking; - uint8_t is_shields; - uint8_t is_offcycle; - uint8_t pad61; - uint8_t pad62; - uint8_t pad63; - uint8_t pad64; -} cbtevent; - -/* agent short */ -typedef struct ag { - char* name; /* agent name. may be null. valid only at time of event. utf8 */ - uintptr_t id; /* agent unique identifier */ - uint32_t prof; /* profession at time of event. refer to evtc notes for identification */ - uint32_t elite; /* elite spec at time of event. refer to evtc notes for identification */ - uint32_t self; /* 1 if self, 0 if not */ - uint16_t team; /* sep21+ */ -} ag; - -enum class HackedMapIds -{ - WVW_LOUNGE = 0x0523, - WVW_EBG = 0x0026, - WVW_GBL = 0x005F, - WVW_BBL = 0x0060, - WVW_RBL = 0x044B -}; - -namespace DATA_ARRAY -{ -enum LAYOUT : uint8_t -{ - Guardian, - Dragonhunter, - Firebrand, - Willbender, - Warrior, - Berserker, - Spellbreaker, - Bladesworn, - Engineer, - Scrapper, - Holosmith, - Mechanist, - Ranger, - Druid, - Soulbeast, - Untamed, - Thief, - Daredevil, - Deadeye, - Specter, - Elementalist, - Tempest, - Weaver, - Catalyst, - Mesmer, - Chronomancer, - Mirage, - Virtuoso, - Necromancer, - Reaper, - Scourge, - Harbinger, - Revenant, - Herald, - Renegade, - Vindicator, - Unknown, - LENGTH -}; -} +#include "../include/types.h" +#include "../include/arcdeeps.h" +void* filelog; const std::array pe_name_lut = { + "Unknown", "Guardian", "Dragonhunter", "Firebrand", @@ -222,11 +53,11 @@ const std::array pe_name_lut = { "Revenant", "Herald", "Renegade", - "Vindicator", - "Unknown", + "Vindicator" }; const std::array pe_short_name_lut = { + "Ukn", "Gdn", "Dgh", "Fbd", @@ -262,230 +93,17 @@ const std::array pe_short_name_lut = { "Rev", "Her", "Ren", - "Vin", - "Ukn" -}; - -struct s_profelite { - uint8_t prof = 0; - uint8_t elite = 0; - uint8_t idx = 0; - uint8_t count = 0; - s_profelite() {} - s_profelite(uint8_t _prof, uint8_t _elite) - { - prof = _prof; - elite = _elite; - switch (_elite) - { - case 0: - switch (_prof) - { - case 1: - idx = DATA_ARRAY::Guardian; - return; - case 2: - idx = DATA_ARRAY::Warrior; - return; - case 3: - idx = DATA_ARRAY::Engineer; - return; - case 4: - idx = DATA_ARRAY::Ranger; - return; - case 5: - idx = DATA_ARRAY::Thief; - return; - case 6: - idx = DATA_ARRAY::Elementalist; - return; - case 7: - idx = DATA_ARRAY::Mesmer; - return; - case 8: - idx = DATA_ARRAY::Necromancer; - return; - case 9: - idx = DATA_ARRAY::Revenant; - return; - default: - idx = DATA_ARRAY::Unknown; - return; - } - case 5: - idx = DATA_ARRAY::Druid; - return; - case 7: - idx = DATA_ARRAY::Daredevil; - return; - case 18: - idx = DATA_ARRAY::Berserker; - return; - case 27: - idx = DATA_ARRAY::Dragonhunter; - return; - case 34: - idx = DATA_ARRAY::Reaper; - return; - case 40: - idx = DATA_ARRAY::Chronomancer; - return; - case 43: - idx = DATA_ARRAY::Scrapper; - return; - case 48: - idx = DATA_ARRAY::Tempest; - return; - case 52: - idx = DATA_ARRAY::Herald; - return; - case 55: - idx = DATA_ARRAY::Soulbeast; - return; - case 56: - idx = DATA_ARRAY::Weaver; - return; - case 57: - idx = DATA_ARRAY::Holosmith; - return; - case 58: - idx = DATA_ARRAY::Deadeye; - return; - case 59: - idx = DATA_ARRAY::Mirage; - return; - case 60: - idx = DATA_ARRAY::Scourge; - return; - case 61: - idx = DATA_ARRAY::Spellbreaker; - return; - case 62: - idx = DATA_ARRAY::Firebrand; - return; - case 63: - idx = DATA_ARRAY::Renegade; - return; - case 64: - idx = DATA_ARRAY::Harbinger; - return; - case 65: - idx = DATA_ARRAY::Willbender; - return; - case 66: - idx = DATA_ARRAY::Virtuoso; - return; - case 67: - idx = DATA_ARRAY::Catalyst; - return; - case 68: - idx = DATA_ARRAY::Bladesworn; - return; - case 69: - idx = DATA_ARRAY::Vindicator; - return; - case 70: - idx = DATA_ARRAY::Mechanist; - return; - case 71: - idx = DATA_ARRAY::Specter; - return; - case 72: - idx = DATA_ARRAY::Untamed; - return; - default: - idx = DATA_ARRAY::Unknown; - return; - } - } -}; - -enum combat_state { - IN_BATTLE, - OUT_BATTLE, -}; - -enum display_state { - BATTLE, - HISTORY_TAB, - HISTORY_COL, - NONE, -}; - -struct s_team_battle { - uint8_t total = 0; - uint8_t total_hit = 0; - std::array profelites = std::array(); -}; - -struct custom_team { - unsigned int id = 0; - std::array name = {0}; + "Vin" }; std::mutex mtx; -/* proto/globals */ -struct settings { - uint32_t magic = 0xC0FFEE; - bool bEnabled = true; - ImGuiWindowFlags wFlags = 0; - bool bToShow = false; - bool bTitleBg = true; - bool bShowColumns = false; - bool bShortNames = false; - unsigned int red_team = 705; - unsigned int green_team = 2739; - unsigned int blue_team = 432; - bool bHideInCombat = false; - custom_team cteam1; - custom_team cteam2; - custom_team cteam3; -}; - -struct ArcContext -{ - struct AgentManager - { - struct AgentDataList - { - struct AgentBlock - { - AgentDataList* agentDataList; - AgentBlock* prev; - AgentBlock* next; - unsigned char* agent; - void* flags; - void* p0; - void* p1; - unsigned short length; - unsigned short cur_i; - unsigned short dataSize; - }; - ArcContext* arcContext; - AgentBlock* tail; - AgentBlock* head; - }; - ArcContext* arcContext; - void* p0; - void* p1; - AgentDataList* agentDataList; - }; - AgentManager* agentManager; - unsigned char pad0[0x4d0-sizeof(AgentManager*)]; - char* gw2_data; - unsigned char pad1[0x628-0x4d0-sizeof(AgentManager*)]; - short map_id; -}; - const uint8_t MAX_HISTORY_SIZE = 8; //power of 2 -const uint8_t MAX_STRING_SIZE = 32; -const uint8_t MAX_TOTAL_STRINGS = 64; // int is_wvw_state = -1; bool mod_key1 = false; bool mod_key2 = false; -uint16_t tab_teamid = 0; +uint16_t tab_team_idx = 0; bool override_tab_max_switch = false; char* arcvers; @@ -495,18 +113,31 @@ extern "C" __declspec(dllexport) void* get_release_addr(); /* arcdps exports */ size_t(*arclog)(char*); void(*arccolors)(ImVec4**); -const char*(*arccontext_0x508)(); wchar_t*(*get_settings_path)(); uint64_t(*get_ui_settings)(); uint64_t(*get_key_settings)(); -ArcContext* arccontext = nullptr; +char* gw2_ctx = nullptr; +char* arcdll = 0; +uint16_t* pNumAgents = 0; +uint16_t* pAgentIds = 0; -std::unordered_map ids = std::unordered_map(); -std::unordered_map> team_history_map = std::unordered_map>(); +struct TeamHistories { + std::vector team_ids; + std::vector> histories; +}; + + +std::vector ids = std::vector(); +TeamHistories team_history_map = { + std::vector(), + std::vector>() +}; std::array, MAX_HISTORY_SIZE> history_labels; -settings kte_settings; +settings kte_settings = {}; +int kte_loaded = 0; +bool reset_pos = false; int history_radio_state = 0; int cur_history_idx = 0; @@ -549,6 +180,13 @@ void init_colors() return; } +/* log to arcdps.log, thread/async safe */ +void log_file(char* str) { + size_t(*log)(char*) = (size_t(*)(char*))filelog; + if (log) (*log)(str); + return; +} + /* window callback -- return is assigned to umsg (return zero to not be processed by arcdps or game) */ uintptr_t mod_wnd(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam) { @@ -590,34 +228,108 @@ uintptr_t mod_wnd(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const L return uMsg; } -bool isWvw() +unsigned int logstart_time = 0xFFFFFFFF; +unsigned int last_cbt_evt = GetTickCount(); +combat_state cmb_state = combat_state::OUT_BATTLE; +bool log_start = false; +bool log_end = false; + +unsigned short(* get_team_id)(const void* agent) = nullptr; + +void setup_new_histories() +{ + bool all_zero = true; + for (auto& team : team_history_map.histories) + all_zero = all_zero && team[cur_history_idx].total == 0; + if (!all_zero) + { + cur_history_idx = (cur_history_idx + 1) & (MAX_HISTORY_SIZE - 1); + for (auto& team : team_history_map.histories) + { + if (team[cur_history_idx].total != 0) + { + team[cur_history_idx].total = 0; + for(auto& profelite : team[cur_history_idx].profelites) + { + profelite.count = 0; + } + } + } + history_to_disp_idx = cur_history_idx; + history_radio_state = 0; + ids.clear(); + override_tab_max_switch = false; + } +} + +uint16_t my_team_id = 0; +bool try_register_agent(const uint16_t id) { - if (arccontext == nullptr) + char* cur_agent; + if (id == 0) return false; - switch ((HackedMapIds)arccontext->map_id) + else if (((cur_agent = read_arc_addr_from_gw2(get_agent(gw2_ctx, id))) != 0) && is_valid_foe(cur_agent)) { - case HackedMapIds::WVW_BBL: - case HackedMapIds::WVW_EBG: - case HackedMapIds::WVW_GBL: - case HackedMapIds::WVW_RBL: - case HackedMapIds::WVW_LOUNGE: + uint8_t self_maybe = is_self(cur_agent); + unsigned short instid = get_instid(cur_agent); + unsigned short team_id = 0; + + team_id = get_team(cur_agent); + + if (team_id == 0 || team_id == 0xFFFF) + return false; + if (self_maybe) + my_team_id = team_id; + if (team_id == my_team_id) + return false; + + unsigned short prof = get_prof(cur_agent); //0 + unsigned short elite = get_elite(cur_agent); //2 + + if (std::find(ids.begin(), ids.end(), instid) != ids.end()) //if found + { + return false; + } + if(log_end) + { + log_end = false; + setup_new_histories(); + } + + std::array* team = 0; + for (int i = 0; i < team_history_map.team_ids.size(); i++) + { + if (team_history_map.team_ids[i] == team_id) + { + team = &team_history_map.histories[i]; + break; + } + } + if (team == 0) + { + team_history_map.team_ids.push_back(team_id); + team_history_map.histories.push_back(std::array()); + team = &team_history_map.histories.back(); + } + ids.push_back(instid); + s_team_battle* cur_team = &(*team)[cur_history_idx]; + + uint8_t idx = 1 + ((prof & 0xFF) - 1)*sizeof(s_profelite); + s_profelite* pe = &(cur_team->profelites[idx + 0]); + pe[0].count += (pe[0].elite == (elite & 0xFF)); //core + pe[1].count += (pe[1].elite == (elite & 0xFF)); //elite + pe[2].count += (pe[2].elite == (elite & 0xFF)); //elite + pe[3].count += (pe[3].elite == (elite & 0xFF)); //elite + cur_team->total++; return true; - default: - return false; } + return false; } -unsigned int logstart_time = 0xFFFFFFFF; -unsigned int last_cbt_evt = 0; -unsigned long long log_end_id = 0; -combat_state cmb_state = combat_state::OUT_BATTLE; -bool log_start = false; - /* combat callback -- may be called asynchronously, use id param to keep track of order, first event id will be 2. return ignored */ /* at least one participant will be party/squad or minion of, or a buff applied by squad in the case of buff remove. not all statechanges present, see evtc statechange enum */ uintptr_t mod_combat(const cbtevent* ev, const ag* src, const ag* dst, const char* skillname, const uint64_t id, const uint64_t revision) { - // Get arccontext if (!ev) { if (!src->elite) @@ -629,7 +341,11 @@ uintptr_t mod_combat(const cbtevent* ev, const ag* src, const ag* dst, const cha // char buf[64] = {0}; // snprintf(buf, 64, "%llx|%llx", src->id, dst->id); // log_arc(buf); - kte_settings.bToShow = isWvw(); + kte_settings.bToShow = isWvw(arcdll); + gw2_ctx = get_arcdeeps((HMODULE)arcdll); + kte_loaded = gw2_ctx != 0 && kte_settings.bToShow; + if (!kte_loaded) + log_arc("maybe? KTE NOT INIT\n"); } } } @@ -639,56 +355,35 @@ uintptr_t mod_combat(const cbtevent* ev, const ag* src, const ag* dst, const cha if (ev->is_statechange == CBTS_LOGSTART) { logstart_time = GetTickCount(); - log_end_id = 1; - log_start = true; } else if (ev->is_statechange == CBTS_LOGEND) { + cmb_state = combat_state::OUT_BATTLE; _strtime_s(&history_labels[cur_history_idx][0], 32); snprintf(&history_labels[cur_history_idx][8], 32-9, " (%ds)", (GetTickCount() - logstart_time)/1000); - cmb_state = combat_state::OUT_BATTLE; - log_end_id = id; - log_start = false; + log_end = true; } if (ev->is_activation || ev->is_buffremove || ev->is_statechange || ev->buff || src->elite == 0xFFFFFFFF || dst->elite == 0xFFFFFFFF || src->prof == 0 || dst->prof == 0) return 0; - if (src && dst && ev->value != 0 && id > log_end_id) + else if (src && dst && ev->value != 0) { + if (gw2_ctx == 0) + return 0; + std::lock_guardlock(mtx); - if (log_start) - cmb_state = combat_state::IN_BATTLE; + cmb_state = combat_state::IN_BATTLE; if (GetTickCount() - last_cbt_evt < 200) return 0; last_cbt_evt = GetTickCount(); - bool all_zero = true; - for (auto& team : team_history_map) - all_zero = all_zero && team.second[cur_history_idx].total == 0; - if (log_end_id == 1 && !all_zero) + for (uint16_t i = 0; i < *pNumAgents; i++) { - log_end_id = 0; - cur_history_idx = (cur_history_idx + 1) & (MAX_HISTORY_SIZE - 1); - for (auto& team : team_history_map) - { - if (team.second[cur_history_idx].total != 0) - { - team.second[cur_history_idx].total = 0; - team.second[cur_history_idx].total_hit = 0; - for(auto& profelite : team.second[cur_history_idx].profelites) - { - profelite.count = 0; - } - } - } - history_to_disp_idx = cur_history_idx; - history_radio_state = 0; - ids.clear(); - override_tab_max_switch = false; + uint16_t id = pAgentIds[i]; + // snprintf(buf, 256, "n: %d i: %d id: %04X\n", *pNumAgents, i, id); + // log_file(buf); + try_register_agent(id); } - - // Parse out combat agents - } } return 0; @@ -710,7 +405,7 @@ void options_end_proc(const char* windowname) ImGui::Text("Custom 1 name:"); ImGui::SameLine(); - ImGui::InputText("##cteam1name", kte_settings.cteam1.name.data(), 16); + ImGui::InputText("##cteam1name", kte_settings.cteam1.name.data(), 32); ImGui::SameLine(); ImGui::Text("id:"); ImGui::SameLine(); @@ -718,7 +413,7 @@ void options_end_proc(const char* windowname) ImGui::Text("Custom 2 name:"); ImGui::SameLine(); - ImGui::InputText("##cteam2name", kte_settings.cteam2.name.data(), 16); + ImGui::InputText("##cteam2name", kte_settings.cteam2.name.data(), 32); ImGui::SameLine(); ImGui::Text("id:"); ImGui::SameLine(); @@ -726,14 +421,18 @@ void options_end_proc(const char* windowname) ImGui::Text("Custom 3 name:"); ImGui::SameLine(); - ImGui::InputText("##cteam3name", kte_settings.cteam3.name.data(), 16); + ImGui::InputText("##cteam3name", kte_settings.cteam3.name.data(), 32); ImGui::SameLine(); ImGui::Text("id:"); ImGui::SameLine(); ImGui::InputInt("##cteam3id", (int *)&kte_settings.cteam3.id, 0, 0); - ImGui::NewLine(); ImGui::Separator(); + if (ImGui::Button("Reset postition")) + { + reset_pos = true; + } + ImGui::Text(" "); if (ImGui::Button("Reset settings")) { kte_settings = settings(); @@ -783,7 +482,7 @@ void draw_bar(const float frac, const char* text, const ImVec4& color) void draw_history_menu() { - if(team_history_map.size() == 0) + if(team_history_map.team_ids.size() == 0) { ImGui::Text("No data..."); } @@ -844,7 +543,6 @@ void imgui_team_class_bars(const s_team_battle& team_combatants_to_disp) } std::array combatants_to_disp = team_combatants_to_disp.profelites; uint8_t total = team_combatants_to_disp.total; - uint8_t total_hit = team_combatants_to_disp.total_hit; std::sort(combatants_to_disp.begin(), combatants_to_disp.end(), [=](s_profelite& a, s_profelite& b) { return a.count > b.count; @@ -876,29 +574,29 @@ void imgui_team_class_bars(const s_team_battle& team_combatants_to_disp) void push_new_team_name(char* buf, const uint16_t team_id) { - if (kte_settings.blue_team == team_id) + if (kte_settings.cteam1.id == team_id) { - snprintf(buf, 32, "Blue"); + snprintf(buf, 32, kte_settings.cteam1.name.data()); } - else if (kte_settings.green_team == team_id) + else if (kte_settings.cteam2.id == team_id) { - snprintf(buf, 32, "Green"); + snprintf(buf, 32, kte_settings.cteam2.name.data()); } - else if (kte_settings.red_team == team_id) + else if (kte_settings.cteam3.id == team_id) { - snprintf(buf, 32, "Red"); + snprintf(buf, 32, kte_settings.cteam3.name.data()); } - else if (kte_settings.cteam1.id == team_id) + else if (kte_settings.blue_team == team_id) { - snprintf(buf, 16, kte_settings.cteam1.name.data()); + snprintf(buf, 32, "Blue"); } - else if (kte_settings.cteam2.id == team_id) + else if (kte_settings.green_team == team_id) { - snprintf(buf, 16, kte_settings.cteam2.name.data()); + snprintf(buf, 32, "Green"); } - else if (kte_settings.cteam3.id == team_id) + else if (kte_settings.red_team == team_id) { - snprintf(buf, 16, kte_settings.cteam3.name.data()); + snprintf(buf, 32, "Red"); } else { @@ -915,12 +613,12 @@ void draw_teams_tabbed() uint8_t cur_max = 0; if (override_tab_max_switch == false) { - for (auto& team : team_history_map) + for (int i = 0; i < team_history_map.team_ids.size(); i++) { - if (team.second[history_to_disp_idx].total > cur_max) + if (team_history_map.histories[i][history_to_disp_idx].total > cur_max) { - cur_max = team.second[history_to_disp_idx].total; - tab_teamid = team.first; + cur_max = team_history_map.histories[i][history_to_disp_idx].total; + tab_team_idx = i; } } } @@ -929,18 +627,18 @@ void draw_teams_tabbed() { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); - for (auto& team : team_history_map) + for (int i = 0; i < team_history_map.team_ids.size(); i++) { col = ImGui::GetColorU32(ImGuiCol_Tab); - if (team.first == tab_teamid) + if (i == tab_team_idx) col = ImGui::GetColorU32(ImGuiCol_TabActive); ImGui::PushStyleColor(ImGuiCol_Button, col); char temp[32] = {0}; - push_new_team_name(temp, team.first); + push_new_team_name(temp, team_history_map.team_ids[i]); if (ImGui::Button(temp)) { override_tab_max_switch = true; - tab_teamid = team.first; + tab_team_idx = i; } ImGui::PopStyleColor(); ImGui::SameLine(); @@ -949,7 +647,7 @@ void draw_teams_tabbed() ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); - imgui_team_class_bars(team_history_map[tab_teamid][history_to_disp_idx]); + imgui_team_class_bars(team_history_map.histories[tab_team_idx][history_to_disp_idx]); ImGui::EndTable(); } ImGui::PopStyleColor(); @@ -962,18 +660,18 @@ void draw_teams_columns() ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, 1)); ImU32 col = ImGui::GetColorU32(ImGuiCol_Tab); ImGui::PushStyleColor(ImGuiCol_TableHeaderBg, col); - if (ImGui::BeginTable("coltable", team_history_map.size(), + if (ImGui::BeginTable("coltable", team_history_map.team_ids.size(), ImGuiTableFlags_BordersInner | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_NoPadOuterX)) { char temp[32] = {0}; - for (auto& team : team_history_map) + for (int i = 0; i < team_history_map.team_ids.size(); i++) { - push_new_team_name(temp, team.first); + push_new_team_name(temp, team_history_map.team_ids[i]); ImGui::TableSetupColumn(temp, ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthStretch); } ImGui::TableNextRow(ImGuiTableRowFlags_Headers); int column = 0; - for (auto& team : team_history_map) + for (int i = 0; i < team_history_map.team_ids.size(); i++) { ImGui::TableSetColumnIndex(column); const char* column_name = ImGui::TableGetColumnName(column); // Retrieve name passed to TableSetupColumn() @@ -985,10 +683,10 @@ void draw_teams_columns() ImGui::TableNextRow(); column = 0; - for (auto& team : team_history_map) + for (int i = 0; i < team_history_map.team_ids.size(); i++) { ImGui::TableSetColumnIndex(column); - imgui_team_class_bars(team_history_map[team.first][history_to_disp_idx]); + imgui_team_class_bars(team_history_map.histories[i][history_to_disp_idx]); column++; } ImGui::EndTable(); @@ -1040,7 +738,7 @@ void draw_battle_wait() display_state get_display_state() { - if (team_history_map.empty()) + if (team_history_map.team_ids.empty()) { return display_state::NONE; } @@ -1059,9 +757,24 @@ display_state get_display_state() return display_state::NONE; } + +int nimgui_proc = 0; +bool not_init_closing = true; uintptr_t imgui_proc(const uint32_t not_charsel_or_loading, const uint32_t hide_if_combat_or_ooc) { - if (not_charsel_or_loading && kte_settings.bEnabled && kte_settings.bToShow && + if (not_init_closing && not_charsel_or_loading && kte_loaded == 0 && nimgui_proc == 600) + { + ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x/4, ImGui::GetIO().DisplaySize.y/2)); + ImGui::SetNextWindowSize(ImVec2(200, 100)); + if (ImGui::Begin("KTE NOT INIT", ¬_init_closing)) + { + ImGui::Text("KTE NOT INIT"); + } + ImGui::End(); + } + else if (not_charsel_or_loading && nimgui_proc < 300) + nimgui_proc++; + else if (not_charsel_or_loading && kte_settings.bEnabled && kte_settings.bToShow && (!kte_settings.bHideInCombat || cmb_state == combat_state::OUT_BATTLE)) { bool made_title_invis = false; @@ -1075,7 +788,17 @@ uintptr_t imgui_proc(const uint32_t not_charsel_or_loading, const uint32_t hide_ ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(100, 10)); + auto style = ImGui::GetStyle(); + if (style.ScrollbarSize == 0) + kte_settings.wFlags |= ImGuiWindowFlags_NoScrollbar; + ImGui::PushID("KTE"); + if (reset_pos) + { + ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x/4, ImGui::GetIO().DisplaySize.y/2)); + ImGui::SetNextWindowSize(ImVec2(200, 100)); + reset_pos = false; + } if (ImGui::Begin("Know thy enemy", &kte_settings.bEnabled, kte_settings.wFlags)) { switch (get_display_state()) @@ -1144,14 +867,28 @@ void init_kte_settings() std::wstring path = std::wstring(get_settings_path()); path = path.substr(0, path.find_last_of(L"\\")+1); path.append(L"know_thy_enemy_settings.bin"); - std::fstream file(path.c_str(), std::fstream::in | std::fstream::out | std::ios::binary); + std::ifstream file(path.c_str(), std::fstream::in | std::ios::binary); std::string line; bool success = false; if (file.good()) { - file.read((char*)&kte_settings, sizeof(settings)); - if(kte_settings.magic == 0xC0FFEE) + settings_old temp = {}; + file.read((char*)&temp, sizeof(settings_old)); + if(temp.magic == 0xC0FFEE) + { + memcpy(&kte_settings, &temp, sizeof(settings_old) - sizeof(custom_team_old)*3); + kte_settings.magic = 0xC1FFEE; + memcpy(&kte_settings.cteam1, &temp.cteam1, sizeof(custom_team_old)); + memcpy(&kte_settings.cteam2, &temp.cteam2, sizeof(custom_team_old)); + memcpy(&kte_settings.cteam3, &temp.cteam3, sizeof(custom_team_old)); success = true; + } + else if(temp.magic == 0xC1FFEE) + { + file.seekg(0, std::ios::beg); + file.read((char*)&kte_settings, sizeof(settings)); + success = true; + } } if (!success) { @@ -1188,7 +925,7 @@ arcdps_exports* mod_init() { arc_exports.imguivers = IMGUI_VERSION_NUM; arc_exports.size = sizeof(arcdps_exports); arc_exports.out_name = "Know thy enemy"; - arc_exports.out_build = "4.6.4"; + arc_exports.out_build = "4.9.13"; arc_exports.imgui = imgui_proc; arc_exports.wnd_nofilter = mod_wnd; arc_exports.combat = mod_combat; @@ -1203,13 +940,17 @@ arcdps_exports* mod_init() { } /* export -- arcdps looks for this exported function and calls the address it returns on client load */ -extern "C" __declspec(dllexport) void* get_init_addr(char* arcversion, ImGuiContext* imguictx, void* id3dptr, HANDLE arcdll, void* mallocfn, void* freefn, uint32_t d3dversion) { +extern "C" __declspec(dllexport) void* get_init_addr(char* arcversion, ImGuiContext* imguictx, void* id3dptr, HANDLE _arcdll, void* mallocfn, void* freefn, uint32_t d3dversion) { // id3dptr is IDirect3D9* if d3dversion==9, or IDXGISwapChain* if d3dversion==11 arcvers = arcversion; + arcdll = (char*)_arcdll; + char* arcCtx = get_arc_context(arcdll); //createthread + pNumAgents = get_p_num_agents(arcCtx); + pAgentIds = get_p_agents(arcCtx); + get_settings_path = (wchar_t*(*)())GetProcAddress((HMODULE)arcdll, "e0"); - // arccontext_0x508 = (const char*(*)())GetProcAddress((HMODULE)arcdll, "e1"); - // arccontext = arccontext_0x508()-0x508; arclog = (size_t(*)(char*))GetProcAddress((HMODULE)arcdll, "e8"); + filelog = (void*)GetProcAddress((HMODULE)arcdll, "e3"); arccolors = (void(*)(ImVec4**))GetProcAddress((HMODULE)arcdll, "e5"); get_ui_settings = (uint64_t(*)())GetProcAddress((HMODULE)arcdll, "e6"); get_key_settings = (uint64_t(*)())GetProcAddress((HMODULE)arcdll, "e7");