Skip to content

Commit

Permalink
Fix custom world rendering feature (#56)
Browse files Browse the repository at this point in the history
* get worldview from argumet

* use as separate function

* draw only for dedicated worldview

* pop the view table

* add guards

* Update README.md

* add self as first argument

* Update README.md

* zaro all bytes there

* add SetCustomRender

* check for enabled

* move up

* Update README.md

* move SetCustomRender implementation into DrawFunc

* rename variable

* remove flag

* use types of Moho

* pop garbage

* Fix

---------

Co-authored-by: KionX <>
  • Loading branch information
4z0t committed Dec 30, 2023
1 parent 4be5bc0 commit 02dd11b
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 23 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -86,11 +86,11 @@ To apply the patches you can use the upload action or do it local via the [patch
- section/StopReclaimWhenPaused.cpp

## Additions
- Adds Custom World Rendering (hooks: `HDraw.cpp`, `GetFPS.cpp`; section: `DrawFunc.cpp`, `DrawCircleSetColor.cpp`)
- Adds Custom World Rendering (hooks: `HDraw.cpp`, `GetFPS.cpp`; section: `DrawFunc.cpp`, `DrawCircleSetColor.cpp`,`WorldView.cpp`)
- `UI_DrawRect(pos:vector, size:float, color:string, thickness?=0.15:float)`
- `UI_DrawCircle(pos:vector, radius:float, color:string, thickness?=0.15:float)`

Both functions must be called within `OnRenderWorld(delta_time)` of `gamemain.lua`. CWR can be enabled with console command `ui_CustomWorldRendering`.
Both functions must be called within `WorldView:OnRenderWorld(delta_time)`. To enable CWR call `WorldView:SetCustomRender(true)` of WorldView you want to draw in. To disable call `WorldView:SetCustomRender(false)` respectively.
- Adds Strategic icon scale support:
- hooks/IconScale.cpp
- section/IconScale.cpp
Expand Down
7 changes: 7 additions & 0 deletions hooks/WorldViewCustomRender.cpp
@@ -0,0 +1,7 @@
#include "../define.h"
asm(
".section h0; .set h0,0x86E5B2;"
"mov [edi+0x178], ebx;"
);


78 changes: 59 additions & 19 deletions section/DrawFunc.cpp
Expand Up @@ -68,6 +68,7 @@ void _DrawCircle(void *batcher, Vector3f *pos, float radius, float thickness, ui
NON_GENERAL_REG(radius)
: "eax");
}

namespace Moho
{
void Import(lua_State *l, const char *filename)
Expand All @@ -77,9 +78,9 @@ namespace Moho
lua_call(l, 1, 1);
}

void *GetWorldCamera()
void *GetWorldCamera(void *worldview)
{
int *camera = *(int **)((int)*((int *)g_WRenViewport + 2128) + 4);
int *camera = *(int **)((int)worldview + 4);
void *projmatrix = (*(void *(__thiscall **)(int *))(*camera + 8))(camera);
return projmatrix;
}
Expand All @@ -106,7 +107,7 @@ namespace Moho
int b;
};

void __stdcall FromSolidColor(Texture *t, unsigned int color) asm("0x4478C0");
void FromSolidColor(Texture *t, unsigned int color) asm("0x4478C0");

Texture FromSolidColor(unsigned int color)
{
Expand Down Expand Up @@ -173,11 +174,12 @@ namespace IWldTerrainRes
} // namespace IWldTerrainRes
bool is_in_render_world = false;

void *_worldview = nullptr;
// UI_Lua DrawRect()
int LuaDrawRect(lua_State *l)
{
int *batcher = *(int **)(((int *)g_WRenViewport) + 2135);
if (batcher == nullptr)
if (batcher == nullptr || _worldview == nullptr)
{
return 0;
}
Expand All @@ -198,7 +200,7 @@ int LuaDrawRect(lua_State *l)
return 0;
}
Vector3f orientation{0, 1, 0};
float lod = Moho::GetLODMetric((float *)Moho::GetWorldCamera(), pos);
float lod = Moho::GetLODMetric((float *)Moho::GetWorldCamera(_worldview), pos);
float thick = std::max(thickness / lod, 2.f);
Vector3f a{0, 0, size};
Vector3f b{size, 0, 0};
Expand All @@ -211,7 +213,7 @@ UIRegFunc DrawRectReg{"UI_DrawRect", "UI_DrawRect(pos:vector, size:float, color:
int LuaDrawCircle(lua_State *l)
{
int *batcher = *(int **)(((int *)g_WRenViewport) + 2135);
if (batcher == nullptr)
if (batcher == nullptr || _worldview == nullptr)
{
return 0;
}
Expand All @@ -231,7 +233,7 @@ int LuaDrawCircle(lua_State *l)
return 0;
}
Vector3f orientation{0, 1, 0};
float lod = Moho::GetLODMetric((float *)Moho::GetWorldCamera(), pos);
float lod = Moho::GetLODMetric((float *)Moho::GetWorldCamera(_worldview), pos);
float a = std::max(thickness / lod, 2.f);
_DrawCircle(batcher, &pos, r, lod * a, color, &orientation);

Expand All @@ -241,12 +243,9 @@ int LuaDrawCircle(lua_State *l)

UIRegFunc DrawCircleReg{"UI_DrawCircle", "UI_DrawCircle(pos:vector, radius:float, color:string, thickness?=0.15:float)", LuaDrawCircle};

bool CustomWorldRendering = false;
ConDescReg CustomWorldRenderingVar{"ui_CustomWorldRendering", "Enables custom world rendering", &CustomWorldRendering};

float delta_frame = 0;

// this world view?
// offset +284 from CUIWorldView
void __thiscall CustomDraw(void *_this, void *batcher)
{
// void *wldmap = IWldTerrainRes::GetWldMap();
Expand All @@ -256,39 +255,80 @@ void __thiscall CustomDraw(void *_this, void *batcher)
// void *map = IWldTerrainRes::GetMap(terrain);
// if (!map)
// return;
if (!CustomWorldRendering)

_worldview = _this;
CUIWorldView *view = (CUIWorldView *)((int)_worldview - 284);

if (!view->GetCustomRenderingEnabled())
return;

// LogF("%p", *(int *)(0x010A6470));//gamesession
// LogF("%p", *(int *)((int)worldview - 284 + 532));

LuaState *state = *(LuaState **)((int)g_CUIManager + 48);
lua_State *l = state->m_state;
Moho::Import(l, "/lua/ui/game/gamemain.lua");
LuaObject *worldviewTable = (LuaObject *)((int)_worldview - 284 + 32);
// Moho::Import(l, "/lua/ui/game/gamemain.lua");
worldviewTable->PushStack(l);
lua_pushstring(l, "OnRenderWorld");
lua_rawget(l, -2);
lua_gettable(l, -2);
if (!lua_isfunction(l, -1))
{
WarningF("%s", "OnRenderWorld not a function");
// pop worldviewTable and the value under 'OnRenderWorld' key
lua_pop(l, 2);
return;
}
int *device = Moho::D3D_GetDevice();
Moho::SetupDevice(device, "primbatcher", "TAlphaBlendLinearSampleNoDepth");
int *camera = *(int **)((int)_this + 4);
void *projmatrix = (*(void *(__thiscall **)(int *))(*camera + 8))(camera);
Moho::CPrimBatcher::ResetBatcher(batcher);
Moho::CPrimBatcher::SetViewProjMatrix(batcher, projmatrix);
Moho::CPrimBatcher::SetViewProjMatrix(batcher, Moho::GetWorldCamera(_worldview));
Moho::CPrimBatcher::Texture t;
Moho::CPrimBatcher::FromSolidColor(&t, 0xFFFFFFFF);
Moho::CPrimBatcher::SetTexture(batcher, &t);

is_in_render_world = true;
lua_pushvalue(l, -2);
lua_pushnumber(l, delta_frame);
if (lua_pcall(l, 1, 0))
if (lua_pcall(l, 2, 0))
{
WarningF("%s", lua_tostring(l, -1));
}
lua_pop(l, 1);
is_in_render_world = false;
Moho::CPrimBatcher::FlushBatcher(batcher);
_worldview = nullptr;
}

int SetCustomRender(lua_State *l)
{
if (lua_gettop(l) != 2)
{
l->LuaState->Error(s_ExpectedButGot, __FUNCTION__, 2, lua_gettop(l));
}
Result<CUIWorldView> r = GetCScriptObject<CUIWorldView>(l, 1);
if (r.IsFail())
{
lua_pushstring(l, r.reason);
lua_error(l);
return 0;
}
CUIWorldView *worldview = r.object;
if (worldview == nullptr)
return 0;

bool state = lua_toboolean(l, 2);
worldview->SetCustomRenderingEnabled(state);
return 0;
}

using WorldViewMethodReg = UIRegFunc<0x00E491E8, 0x00F8D88C>;

WorldViewMethodReg WorldViewSetCustomRender{
"SetCustomRender",
"WorldView:SetCustomRender(bool)",
SetCustomRender,
"CUIWorldView"};

void CustomDrawEnter()
{
asm(
Expand Down
5 changes: 3 additions & 2 deletions section/WorldView.cpp
Expand Up @@ -25,7 +25,8 @@ Vector2f ProjectVec(const Vector3f &v, float *camera)
void ProjectVectors(lua_State *l, int index, float *camera)
{
const char *t = (const char *)lua_topointer(l, index);
uint32_t asize; uint8_t hbits;
uint32_t asize;
uint8_t hbits;
GetTableAH(t, &asize, &hbits);
lua_createtable(l, asize, hbits); // result table
lua_pushvalue(l, index); // input vectors
Expand Down Expand Up @@ -84,4 +85,4 @@ WorldViewMethodReg WorldViewProjectMultiple{
"ProjectMultiple",
"WorldView:ProjectMultiple(vectors)",
ProjectMultiple,
"CUIWorldView"};
"CUIWorldView"};
10 changes: 10 additions & 0 deletions section/include/moho.h
Expand Up @@ -203,6 +203,16 @@ struct CUIWorldView : CMauiControl
// at 0x208
CWldSession *session;
void *unk1; // If shift pressed

bool GetCustomRenderingEnabled()const
{
return *(char*)((int)this + 377);
}

void SetCustomRenderingEnabled(bool state)
{
*(char*)((int)this + 377) = state;
}
};

struct RBlueprint;
Expand Down

0 comments on commit 02dd11b

Please sign in to comment.