diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index 9afeb6f..dffcce0 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -43,6 +43,7 @@ target_link_libraries(client gx model net + sound ui util world diff --git a/src/client/Client.cpp b/src/client/Client.cpp index a12dd84..143ac86 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -18,6 +18,7 @@ #include "gx/Texture.hpp" #include "model/Model2.hpp" #include "net/Poll.hpp" +#include "sound/SI2.hpp" #include "ui/FrameScript.hpp" #include "ui/FrameXML.hpp" #include "world/World.hpp" @@ -728,7 +729,7 @@ void WowClientInit() { FrameScript_Initialize(0); // TODO - // SI2::Init(0); + SI2::Init(0); // sub_6F66B0(); FrameXML_RegisterDefault(); diff --git a/src/gameui/GameScriptFunctions.cpp b/src/gameui/GameScriptFunctions.cpp index 2480b7f..1dc6fe3 100644 --- a/src/gameui/GameScriptFunctions.cpp +++ b/src/gameui/GameScriptFunctions.cpp @@ -8,11 +8,13 @@ #include "gameui/CGTabardModelFrame.hpp" #include "gameui/CGQuestPOIFrame.hpp" #include "console/Console.hpp" +#include "console/CVar.hpp" #include "gx/CGVideoOptions.hpp" #include "ui/FrameXML.hpp" #include "ui/FrameScript.hpp" #include "util/Lua.hpp" #include "util/Unimplemented.hpp" +#include "util/StringTo.hpp" // External from "ui/ScriptFunctions.hpp" void RegisterSimpleFrameScriptMethods(); @@ -163,31 +165,142 @@ static int32_t Script_SetCVar(lua_State* L) { } static int32_t Script_GetCVar(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + return luaL_error(L, "Usage: GetCVar(\"cvar\")"); + } + + // TODO: Use LookupRegistered + auto cvar = CVar::Lookup(lua_tolstring(L, 1, nullptr)); + if (!cvar || (cvar->m_flags & 0x40)) { + lua_pushnil(L); + } else { + lua_pushstring(L, cvar->GetString()); + } + return 1; } static int32_t Script_GetCVarBool(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + return luaL_error(L, "Usage: GetCVarBool(\"cvar\")"); + } + + // TODO: Use LookupRegistered + auto cvar = CVar::Lookup(lua_tolstring(L, 1, nullptr)); + if (cvar && (cvar->m_flags & 0x40) == 0 && StringToBOOL(cvar->GetString())) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + return 1; } static int32_t Script_GetCVarDefault(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + return luaL_error(L, "Usage: GetCVarDefault(\"cvar\")"); + } + + auto name = lua_tolstring(L, 1, nullptr); + // TODO: Use LookupRegistered + auto cvar = CVar::Lookup(name); + if (!cvar || (cvar->m_flags & 0x40)) { + return luaL_error(L, "Couldn't find CVar named '%s'", name); + } else { + lua_pushstring(L, cvar->m_defaultValue.GetString()); + } + return 1; } static int32_t Script_GetCVarMin(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + return luaL_error(L, "Usage: GetCVarMin(\"cvar\")"); + } + + auto name = lua_tolstring(L, 1, nullptr); + // TODO: Use LookupRegistered + auto cvar = CVar::Lookup(name); + if (!cvar || (cvar->m_flags & 0x40)) { + return luaL_error(L, "Couldn't find CVar named '%s'", name); + } + + auto key = cvar->m_key.m_str; + if (!SStrCmpI(key, "extShadowQuality", STORM_MAX_STR)) { + lua_pushnumber(L, 0.0); + } else if (!SStrCmpI(key, "farclip", STORM_MAX_STR)) { + lua_pushnumber(L, 177.0); + } else { + lua_pushnil(L); + } + + return 1; } static int32_t Script_GetCVarMax(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + return luaL_error(L, "Usage: GetCVarMax(\"cvar\")"); + } + + auto name = lua_tolstring(L, 1, nullptr); + // TODO: Use LookupRegistered + auto cvar = CVar::Lookup(name); + if (!cvar || (cvar->m_flags & 0x40)) { + return luaL_error(L, "Couldn't find CVar named '%s'", name); + } + + auto key = cvar->m_key.m_str; + if (!SStrCmpI(key, "extShadowQuality", STORM_MAX_STR)) { + // TODO + lua_pushnumber(L, 1.0); + } else if (!SStrCmpI(key, "farclip", STORM_MAX_STR)) { + lua_pushnumber(L, 1277.0); + } else { + lua_pushnil(L); + } + + return 1; } static int32_t Script_GetCVarAbsoluteMin(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + return luaL_error(L, "Usage: GetCVarAbsoluteMin(\"cvar\")"); + } + + auto name = lua_tolstring(L, 1, nullptr); + // TODO: Use LookupRegistered + auto cvar = CVar::Lookup(name); + if (!cvar || (cvar->m_flags & 0x40)) { + return luaL_error(L, "Couldn't find CVar named '%s'", name); + } + + auto key = cvar->m_key.m_str; + if (!SStrCmpI(key, "extShadowQuality", STORM_MAX_STR)) { + lua_pushnumber(L, 0.0); + } else { + lua_pushnil(L); + } + + return 1; } static int32_t Script_GetCVarAbsoluteMax(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isstring(L, 1)) { + return luaL_error(L, "Usage: GetCVarAbsoluteMax(\"cvar\")"); + } + + auto name = lua_tolstring(L, 1, nullptr); + // TODO: Use LookupRegistered + auto cvar = CVar::Lookup(name); + if (!cvar || (cvar->m_flags & 0x40)) { + return luaL_error(L, "Couldn't find CVar named '%s'", name); + } + + auto key = cvar->m_key.m_str; + if (!SStrCmpI(key, "extShadowQuality", STORM_MAX_STR)) { + lua_pushnumber(L, 5.0); + } else { + lua_pushnil(L); + } + + return 1; } static int32_t Script_GetWaterDetail(lua_State* L) { diff --git a/src/sound/SI2.cpp b/src/sound/SI2.cpp index 54d90a2..cc5890f 100644 --- a/src/sound/SI2.cpp +++ b/src/sound/SI2.cpp @@ -30,6 +30,8 @@ void SI2::RegisterScriptFunctions() { } int32_t SI2::Init(int32_t flag) { + SI2::RegisterCVars(); + Log_Init(); SI2_LOG("=> Version %s (%s) %s", "1.0.0", "00000", "Feb 25 2024"); SI2_LOG(" "); diff --git a/src/ui/CSimpleFrameScript.cpp b/src/ui/CSimpleFrameScript.cpp index 2b68e78..65feedd 100644 --- a/src/ui/CSimpleFrameScript.cpp +++ b/src/ui/CSimpleFrameScript.cpp @@ -180,11 +180,58 @@ int32_t CSimpleFrame_HasScript(lua_State* L) { } int32_t CSimpleFrame_GetScript(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + int32_t type = CSimpleFrame::GetObjectType(); + CSimpleFrame* frame = static_cast(FrameScript_GetObjectThis(L, type)); + + if (!lua_isstring(L, 2)) { + return luaL_error(L, "Usage: %s:GetScript(\"type\")", frame->GetDisplayName()); + } + + auto scriptName = lua_tolstring(L, 2, nullptr); + + FrameScript_Object::ScriptData scriptData; + auto script = frame->GetScriptByName(scriptName, scriptData); + if (!script) { + return luaL_error(L, "%s doesn't have a \"%s\" script", frame->GetDisplayName(), scriptName); + } + + // TODO: if (script->unk && lua_taintexpected && !lua_taintedclosure ) + + if (script->luaRef <= 0) { + lua_pushnil(L); + } else { + lua_rawgeti(L, LUA_REGISTRYINDEX, script->luaRef); + } + return 1; } int32_t CSimpleFrame_SetScript(lua_State* L) { + // WARNING: This implementation breaks the client WHOA_UNIMPLEMENTED(0); + + int32_t type = CSimpleFrame::GetObjectType(); + CSimpleFrame* frame = static_cast(FrameScript_GetObjectThis(L, type)); + + if (!lua_isstring(L, 2) || (lua_type(L, 3) != LUA_TFUNCTION && lua_type(L, 3) != LUA_TNIL)) { + return luaL_error(L, "Usage: %s:SetScript(\"type\", function)", frame->GetDisplayName()); + } + + auto scriptName = lua_tolstring(L, 2, nullptr); + + FrameScript_Object::ScriptData scriptData; + auto script = frame->GetScriptByName(scriptName, scriptData); + if (!script) { + return luaL_error(L, "%s doesn't have a \"%s\" script", frame->GetDisplayName(), scriptName); + } + + if (script->luaRef) { + luaL_unref(L, LUA_REGISTRYINDEX, script->luaRef); + } + + auto ref = luaL_ref(L, LUA_REGISTRYINDEX); + script->luaRef = ref <= 0 ? 0 : ref; + // TODO: script->unk = lua_tainted; + return 0; } int32_t CSimpleFrame_HookScript(lua_State* L) { diff --git a/src/ui/CSimpleMessageScrollFrame.hpp b/src/ui/CSimpleMessageScrollFrame.hpp index deadef1..1e793ba 100644 --- a/src/ui/CSimpleMessageScrollFrame.hpp +++ b/src/ui/CSimpleMessageScrollFrame.hpp @@ -20,6 +20,10 @@ class CSimpleMessageScrollFrame : public CSimpleHyperlinkedFrame { // Virtual member functions virtual bool IsA(int32_t type); virtual int32_t GetScriptMetaTable(); + + // Member variables + int32_t m_atTop = 0; + int32_t m_atBottom = 1; }; #endif diff --git a/src/ui/CSimpleMessageScrollFrameScript.cpp b/src/ui/CSimpleMessageScrollFrameScript.cpp index f6791b1..f39d4e8 100644 --- a/src/ui/CSimpleMessageScrollFrameScript.cpp +++ b/src/ui/CSimpleMessageScrollFrameScript.cpp @@ -108,11 +108,25 @@ static int32_t Script_SetScrollOffset(lua_State* L) { } static int32_t Script_AtTop(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleMessageScrollFrame::GetObjectType(); + auto frame = static_cast(FrameScript_GetObjectThis(L, type)); + if (frame->m_atTop) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + return 1; } static int32_t Script_AtBottom(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleMessageScrollFrame::GetObjectType(); + auto frame = static_cast(FrameScript_GetObjectThis(L, type)); + if (frame->m_atBottom) { + lua_pushnumber(L, 1.0); + } else { + lua_pushnil(L); + } + return 1; } static int32_t Script_UpdateColorByID(lua_State* L) { diff --git a/src/ui/CSimpleStatusBar.cpp b/src/ui/CSimpleStatusBar.cpp index b07e28d..0e9107b 100644 --- a/src/ui/CSimpleStatusBar.cpp +++ b/src/ui/CSimpleStatusBar.cpp @@ -27,6 +27,11 @@ CSimpleStatusBar::CSimpleStatusBar(CSimpleFrame* parent) : CSimpleFrame(parent) { } +void CSimpleStatusBar::SetOrientation(uint32_t orientation) { + this->m_flags |= 1; + this->m_orientation = orientation; +} + bool CSimpleStatusBar::IsA(int32_t type) { return type == CSimpleStatusBar::s_objectType || type == CSimpleFrame::s_objectType diff --git a/src/ui/CSimpleStatusBar.hpp b/src/ui/CSimpleStatusBar.hpp index e7973b3..180d831 100644 --- a/src/ui/CSimpleStatusBar.hpp +++ b/src/ui/CSimpleStatusBar.hpp @@ -16,6 +16,7 @@ class CSimpleStatusBar : public CSimpleFrame { // Member functions CSimpleStatusBar(CSimpleFrame* parent); + void SetOrientation(uint32_t orientation); // Virtual member functions virtual bool IsA(int32_t type); @@ -23,6 +24,12 @@ class CSimpleStatusBar : public CSimpleFrame { virtual ScriptIx* GetScriptByName(const char* name, ScriptData& data); // Member variables + uint32_t m_flags = 0; + float m_minValue = 0.0f; + float m_maxValue = 0.0f; + float m_value = 0.0f; + CSimpleTexture* m_barTexture = nullptr; + uint32_t m_orientation = 0; ScriptIx m_onValueChanged; ScriptIx m_onMinMaxChanged; }; diff --git a/src/ui/CSimpleStatusBarScript.cpp b/src/ui/CSimpleStatusBarScript.cpp index 1172af4..aacd6a2 100644 --- a/src/ui/CSimpleStatusBarScript.cpp +++ b/src/ui/CSimpleStatusBarScript.cpp @@ -1,18 +1,40 @@ #include "ui/CSimpleStatusBarScript.hpp" #include "ui/CSimpleStatusBar.hpp" +#include "ui/Util.hpp" #include "util/Lua.hpp" #include "util/Unimplemented.hpp" +#include "util/StringTo.hpp" static int32_t Script_GetOrientation(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleStatusBar::GetObjectType(); + auto statusBar = static_cast(FrameScript_GetObjectThis(L, type)); + lua_pushstring(L, OrientationToString(statusBar->m_orientation)); + return 1; } static int32_t Script_SetOrientation(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleStatusBar::GetObjectType(); + auto statusBar = static_cast(FrameScript_GetObjectThis(L, type)); + if (!lua_isstring(L, 2)) { + return luaL_error(L, "Usage: %s:SetOrientation(\"orientation\")", statusBar->GetDisplayName()); + } + + auto string = lua_tolstring(L, 2, nullptr); + uint32_t orientation = 0; + if (!StringToOrientation(string, orientation)) { + return luaL_error(L, "%s:SetOrientation(): Unknown orientation: %s", statusBar->GetDisplayName(), string); + } + + statusBar->SetOrientation(orientation); + return 0; } static int32_t Script_GetMinMaxValues(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleStatusBar::GetObjectType(); + auto statusBar = static_cast(FrameScript_GetObjectThis(L, type)); + lua_pushnumber(L, statusBar->m_minValue); + lua_pushnumber(L, statusBar->m_maxValue); + return 2; } static int32_t Script_SetMinMaxValues(lua_State* L) { @@ -20,7 +42,10 @@ static int32_t Script_SetMinMaxValues(lua_State* L) { } static int32_t Script_GetValue(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + auto type = CSimpleStatusBar::GetObjectType(); + auto statusBar = static_cast(FrameScript_GetObjectThis(L, type)); + lua_pushnumber(L, statusBar->m_value); + return 1; } static int32_t Script_SetValue(lua_State* L) { diff --git a/src/ui/Util.cpp b/src/ui/Util.cpp index ecf4f0b..1b6c069 100644 --- a/src/ui/Util.cpp +++ b/src/ui/Util.cpp @@ -86,3 +86,14 @@ int32_t StringToFrameStrata(const char* string, FRAME_STRATA& strata) { return 0; } + +const char* OrientationToString(uint32_t orientation) { + switch (orientation) { + case 0: + return "HORIZONTAL"; + case 1: + return "VERTICAL"; + default: + return "UNKNOWN"; + } +} diff --git a/src/ui/Util.hpp b/src/ui/Util.hpp index c7f813b..38b5d5a 100644 --- a/src/ui/Util.hpp +++ b/src/ui/Util.hpp @@ -13,4 +13,6 @@ int32_t StringToFramePoint(const char* string, FRAMEPOINT& point); int32_t StringToFrameStrata(const char* string, FRAME_STRATA& strata); +const char* OrientationToString(uint32_t orientation); + #endif diff --git a/src/util/StringTo.cpp b/src/util/StringTo.cpp index aaf1f77..49506e6 100644 --- a/src/util/StringTo.cpp +++ b/src/util/StringTo.cpp @@ -159,3 +159,14 @@ int32_t StringToJustify(const char* string, uint32_t& justify) { return 0; } + +bool StringToOrientation(const char* string, uint32_t& orientation) { + if (!SStrCmpI(string, "HORIZONTAL", STORM_MAX_STR)) { + orientation = 0; + return true; + } else if (!SStrCmpI(string, "VERTICAL", STORM_MAX_STR)) { + orientation = 1; + return true; + } + return false; +} diff --git a/src/util/StringTo.hpp b/src/util/StringTo.hpp index 18d4825..1fb435f 100644 --- a/src/util/StringTo.hpp +++ b/src/util/StringTo.hpp @@ -17,4 +17,6 @@ int32_t StringToDrawLayer(const char*, int32_t&); int32_t StringToJustify(const char*, uint32_t&); +bool StringToOrientation(const char* string, uint32_t& orientation); + #endif diff --git a/src/util/Unimplemented.hpp b/src/util/Unimplemented.hpp index 1044889..aee36f8 100644 --- a/src/util/Unimplemented.hpp +++ b/src/util/Unimplemented.hpp @@ -2,10 +2,11 @@ #define UTIL_UNIMPLEMENTED_HPP #include +#include "os/Debug.hpp" -#define WHOA_UNIMPLEMENTED(...) \ - fprintf(stderr, "Function not yet implemented: %s in %s (line %i)\n", __FUNCTION__, __FILE__, __LINE__); \ - return __VA_ARGS__; \ +#define WHOA_UNIMPLEMENTED(...) \ + OsOutputDebugString("Function not yet implemented: %s in %s (line %i)\n", __FUNCTION__, __FILE__, __LINE__); \ + return __VA_ARGS__; \ (void)0 #endif