-
Notifications
You must be signed in to change notification settings - Fork 10
Allies intel range rings #142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 7 commits
b9cbe9d
813d9ab
1c6ba97
fd5ea0e
ecca354
f1285c1
70be9bf
30dd2f7
58f9939
90fa4a0
9cd458a
e5873d0
ae76cc8
9b7a555
d529df5
36c9140
5c6fca4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| 0x007A7858: | ||
| jmp asm__ShouldAddUnit | ||
| nop | ||
|
|
||
| 0x00E4D984: | ||
| .int Moho__UserUnit__GetIntelRanges | ||
|
|
||
| 0x007EF12B: | ||
| push esp | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you push stack pointer? Why not use
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. push = 1 byte |
||
| mov ecx, esi | ||
| call RenderRange__Moho__UserUnit__UserUnit | ||
| nop | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| extern "C" void __attribute__((naked)) asm__ShouldAddUnit() { | ||
| asm volatile(R"( | ||
| push ecx; | ||
| push edx; | ||
| push edi; | ||
| push eax; | ||
| call _ShouldAddUnit; | ||
| add esp, 8; | ||
| pop edx; | ||
| pop ecx; | ||
| test al,al; | ||
| je 0x007A789F; | ||
| jmp 0x007A7860;)"); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| #include "global.h" | ||
| #include "magic_classes.h" | ||
|
|
||
| static bool map_has_unit(uintptr_t map_base, uintptr_t key) { | ||
| auto head = *reinterpret_cast<uintptr_t*>(map_base + 0x04); | ||
| auto node = *reinterpret_cast<uintptr_t*>(head + 0x04); | ||
| while (node) { | ||
| if (*reinterpret_cast<uint8_t*>(node + 0x19)) // _Isnil (0x19) | ||
| return false; | ||
| auto node_key = *reinterpret_cast<uintptr_t*>(node + 0x0C); | ||
| if (key < node_key) | ||
| node = *reinterpret_cast<uintptr_t*>(node + 0x00); // _Left (0x00) | ||
| else if (key > node_key) | ||
| node = *reinterpret_cast<uintptr_t*>(node + 0x08); // _Right (0x08) | ||
| else | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| enum IntelRangeBehavior { | ||
| kOwnUnits = 0, | ||
| kOwnUnitsAndAlliedBuildings = 1, | ||
| kOwnUnitsAndAlliedUnits = 2 | ||
| }; | ||
|
|
||
| int intelRangeBehavior = kOwnUnitsAndAlliedBuildings; | ||
| ConDescReg conIntelRangeBehavior{"ren_IntelRangeBehavior", | ||
| "Only own units = 0; Own units and allied " | ||
| "buildings = 1; Own and allied units = 2", | ||
| &intelRangeBehavior}; | ||
|
|
||
| extern "C" { | ||
|
|
||
| uintptr_t __thiscall RenderRange__Moho__UserUnit__UserUnit(uintptr_t this_, | ||
| uintptr_t esp) { | ||
| // Compiler, I believe in you. We're in a hot path, optimize and inline the | ||
| // lambda pls p.s. I saw the listing, mine handled it, and there’s no call | ||
| // there | ||
| auto equals = []<size_t N>(string& str1, const char (&str2)[N]) { | ||
| if (str1.strLen != N - 1) return false; | ||
| const char* l = str1.data(); | ||
| const char* r = str2; | ||
| while (*l == *r && *l) { | ||
| ++l; | ||
| ++r; | ||
| }; | ||
| return (*l - *r) == 0; | ||
| }; | ||
| auto& rangeName = **reinterpret_cast<string**>(esp + 0x30); | ||
| bool isIntelRange = equals(rangeName, "Radar") || equals(rangeName, "Omni") || | ||
| equals(rangeName, "Sonar"); | ||
| if (isIntelRange) return this_; | ||
|
|
||
| auto session = *reinterpret_cast<uintptr_t*>(0x10A6470); | ||
| auto focusArmyIndex = *reinterpret_cast<int*>(session + 0x488); | ||
| auto unitArmy = *reinterpret_cast<uintptr_t*>(this_ + 0x120); | ||
| auto unitArmyIndex = *reinterpret_cast<int*>(unitArmy); | ||
| if (unitArmyIndex == focusArmyIndex) return this_; | ||
| return 0; | ||
| } | ||
|
|
||
| // Initially, the game receives the ranges from the current state of the unit, | ||
| // not directly from its blueprint. However, the full state of the unit is only | ||
| // available to its owner. Since this function is called in RangeExtractors, we | ||
| // also need to get the ranges of allies; the original would return 0 0 0 for | ||
| // units not belonging to its army. Rewrite 00E3F980 (RadarExtractor), 00E3F998 | ||
| // (Sonar), 00E3F978 (Omni), and you won't need this | ||
| bool __thiscall Moho__UserUnit__GetIntelRanges(uintptr_t this_, | ||
| float* omniRange, | ||
| float* radarRange, | ||
| float* sonarRange) { | ||
| if ((*reinterpret_cast<uint8_t*>(this_ + 0x39C) & 8) != 0 && | ||
| (*reinterpret_cast<uint8_t*>(this_ + 0x3A8) & 8) != 0) | ||
| return false; | ||
| auto blueprint = *reinterpret_cast<uintptr_t*>(this_ + 0x48); | ||
| auto intelRanges = reinterpret_cast<uint32_t*>(blueprint + 0x338); | ||
| *radarRange = intelRanges[0]; | ||
| *sonarRange = intelRanges[1]; | ||
| *omniRange = intelRanges[2]; | ||
| return (*radarRange > 0.0f || *sonarRange > 0.0f || *omniRange > 0.0f); | ||
| } | ||
|
RutreD marked this conversation as resolved.
|
||
|
|
||
| bool __cdecl ShouldAddUnit(void* focusArmy, uintptr_t userUnit) { | ||
| auto session = *reinterpret_cast<uintptr_t*>(0x10A6470); | ||
| auto unitArmy = *reinterpret_cast<void**>(userUnit + 0x120); | ||
| if (unitArmy == focusArmy) { | ||
| // Optimization: To avoid double rendering, | ||
| // do not render the global rings; | ||
| // they will be rendered in the selection rings render | ||
| auto selectionSize = *(size_t*)(session + 0x4A8); | ||
| [[likely]] if (selectionSize < 67) | ||
| return true; | ||
| return !map_has_unit(session + 0x4A0, userUnit); | ||
| } | ||
|
|
||
| if (intelRangeBehavior == kOwnUnits) return false; | ||
|
|
||
| auto focusArmyIndex = *reinterpret_cast<int*>(session + 0x488); | ||
| if (!Army_IsAlly(focusArmyIndex, unitArmy)) return false; | ||
|
RutreD marked this conversation as resolved.
Outdated
|
||
|
|
||
| auto blueprint = *reinterpret_cast<uintptr_t*>(userUnit + 0x48); | ||
| if (intelRangeBehavior == kOwnUnitsAndAlliedBuildings && | ||
| *reinterpret_cast<uint32_t*>(blueprint + 0x290) != 0) | ||
| // MotionType != None -> let's assume this is not a building | ||
| return false; | ||
|
|
||
| auto intel = reinterpret_cast<uint32_t*>(blueprint + 0x338); | ||
| bool hasIntel = (intel[0] | intel[1] | intel[2]) != 0; | ||
| return hasIntel; | ||
| } | ||
|
|
||
| } // extern "C" | ||
Uh oh!
There was an error while loading. Please reload this page.