diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml
new file mode 100644
index 0000000..d207c84
--- /dev/null
+++ b/.github/workflows/msbuild.yml
@@ -0,0 +1,93 @@
+name: MSBuild
+
+on:
+  push:
+    branches: [ "dev" ]
+
+env:
+  SOLUTION_FILE_PATH: JG/johnnyguitar.sln
+
+permissions: write-all
+
+jobs:
+  build:
+    runs-on: windows-latest
+
+    steps:
+    - uses: actions/checkout@v4
+
+    - name: Add MSBuild to PATH
+      uses: microsoft/setup-msbuild@v2
+
+    - name: Build Release
+      working-directory: ${{env.GITHUB_WORKSPACE}}
+      run: msbuild /m /p:Configuration=Release ${{env.SOLUTION_FILE_PATH}} /p:PostBuildEventUseInBuild=false
+
+    - name: Build Debug
+      working-directory: ${{env.GITHUB_WORKSPACE}}
+      run: msbuild /m /p:Configuration=Debug ${{env.SOLUTION_FILE_PATH}} /p:PostBuildEventUseInBuild=false
+
+    - name: Generate Timestamp
+      run: |
+        timestamp=$(date +"%Y%m%d%H%M%S")
+        echo "artifact_timestamp=$timestamp" >> $GITHUB_ENV
+      shell: bash
+
+    - name: Package Artifacts
+      run: |
+        mkdir -p artifacts
+        Compress-Archive -Path JG\Release\johnnyguitar.dll -DestinationPath artifacts\JohnnyGuitarNVSE-Release-${{ env.artifact_timestamp }}.zip
+        Compress-Archive -Path JG\Debug\johnnyguitar.dll -DestinationPath artifacts\JohnnyGuitarNVSE-Debug-${{ env.artifact_timestamp }}.zip
+      shell: pwsh
+
+    - name: Publish Zipped Artifacts
+      uses: actions/upload-artifact@v4
+      with:
+        name: Zipped-Artifacts-${{ env.artifact_timestamp }}
+        path: artifacts/
+
+    - name: Get Release
+      id: get_release
+      uses: cardinalby/git-get-release-action@v1
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        tag: 'continuous'
+        doNotFailIfNotFound: true
+    - name: Delete old release if exists
+      if: steps.get_release.outputs.id != ''
+      uses: dev-drprasad/delete-tag-and-release@v1.0
+      with:
+        tag_name: continuous
+        github_token: ${{ secrets.GITHUB_TOKEN }}
+        delete_release: true
+    - name: Create Release
+      id: create_release
+      uses: actions/create-release@v1
+      env:
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        tag_name: continuous
+        release_name: "Continuous release"
+        draft: false
+        prerelease: true
+        body: |
+          Continuous release generated from the latest push to development branch.
+    - name: Upload Artifact (Release)
+      uses: actions/upload-release-asset@v1
+      env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        upload_url: ${{ steps.create_release.outputs.upload_url }}
+        asset_path: artifacts/JohnnyGuitarNVSE-Release-${{ env.artifact_timestamp }}.zip
+        asset_name: JohnnyGuitarNVSE-Release-${{ env.artifact_timestamp }}.zip
+        asset_content_type: application/zip
+    - name: Upload Artifact (Debug)
+      uses: actions/upload-release-asset@v1
+      env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        upload_url: ${{ steps.create_release.outputs.upload_url }}
+        asset_path: artifacts/JohnnyGuitarNVSE-Debug-${{ env.artifact_timestamp }}.zip
+        asset_name: JohnnyGuitarNVSE-Debug-${{ env.artifact_timestamp }}.zip
+        asset_content_type: application/zip
diff --git a/JG/JohnnyGuitarNVSE.cpp b/JG/JohnnyGuitarNVSE.cpp
index 731b363..f30f5fe 100644
--- a/JG/JohnnyGuitarNVSE.cpp
+++ b/JG/JohnnyGuitarNVSE.cpp
@@ -75,6 +75,8 @@ void MessageHandler(NVSEMessagingInterface::Message* msg) {
 		hk_BarterHook::barterFilterListRight.clear();
 		NPCAccuracy::FlushMapRefs();
 		shakeRequests.clear();
+		mlcOverridden = false;
+		mlcOverride = nullptr;
 		break;
 	}
 	case NVSEMessagingInterface::kMessage_PostLoadGame:
@@ -496,8 +498,11 @@ extern "C" {
 		REG_CMD(RemoveNoteQuest);
 		REG_CMD(SetHUDShudderPower);
 		REG_CMD(GetHUDShudderPower);
-		REG_CMD(SetDialogResponseOverrideValues); // Function is subject to overrides at random and therefore not eligible for documentation. Can be removed at any time, so mod breakage due to using it will not be considered.
-
+		REG_CMD(SetDialogResponseOverrideValues); // do not document
+		REG_CMD(SetMediaLocationControllerOverride); // do not document
+		REG_CMD(ClearMediaLocationControllerOverride); // do not document
+		REG_CMD(GetCasinoWinnings);
+		REG_CMD(SetCasinoWinnings);
 		g_scriptInterface = (NVSEScriptInterface*)nvse->QueryInterface(kInterface_Script);
 		g_cmdTableInterface = (NVSECommandTableInterface*)nvse->QueryInterface(kInterface_CommandTable);
 		s_strArgBuf = (char*)malloc((sizeof(char)) * 1024);
diff --git a/JG/JohnnyGuitarNVSE.h b/JG/JohnnyGuitarNVSE.h
index 249eeee..352e91f 100644
--- a/JG/JohnnyGuitarNVSE.h
+++ b/JG/JohnnyGuitarNVSE.h
@@ -69,7 +69,8 @@ Setting** g_miscStatData = (Setting**)0x11C6D50;
 char g_workingDir[MAX_PATH];
 std::unordered_set<DWORD> jg_gameRadioSet;
 static float g_viewmodel_near = 0.f;
-
+bool mlcOverridden = false;
+MediaLocationController* mlcOverride = nullptr;
 extern "C" {
 	bool __cdecl JGSetViewmodelClipDistance(float value);
 	float __cdecl JGGetViewmodelClipDistance();
@@ -601,6 +602,7 @@ namespace hk_DialogueTopicResponseManageHook {
 			}
 		}
 		PrintLog("End Dialogue Dump");
+		return NULL;
 
 	}
 
@@ -1817,6 +1819,17 @@ __declspec (noinline) void HandleDLLInterop() {
 	}
 }
 
+
+MediaLocationController* __fastcall MLCOverrideHook(PlayerCharacter* player)
+{
+	if (mlcOverridden)
+	{
+		return mlcOverride;
+	}
+	return ThisStdCall<MediaLocationController*>(0x9698A0, player);
+
+}
+
 float getHUDShakePower() {
 	if (shakeRequests.empty()) {
 		return 0.0f;
@@ -1885,6 +1898,8 @@ void HandleFunctionPatches() {
 
 	WriteRelCall(0x8752F2, UInt32(SetViewmodelFrustumHook));
 
+	WriteRelCall(0x82FC95, (UInt32)MLCOverrideHook);
+
 }
 float timer22 = 30.0;
 void HandleGameHooks() {
diff --git a/JG/functions/fn_gameplay.h b/JG/functions/fn_gameplay.h
index 303c1c2..d074af7 100644
--- a/JG/functions/fn_gameplay.h
+++ b/JG/functions/fn_gameplay.h
@@ -1,4 +1,5 @@
 #pragma once
+#include "ParamInfos.h"
 // Functions affecting gameplay
 DEFINE_COMMAND_PLUGIN(ToggleLevelUpMenu, , 0, 1, kParams_OneInt);
 DEFINE_COMMAND_PLUGIN(TogglePipBoy, , 0, 1, kParams_OneOptionalInt);
@@ -58,6 +59,11 @@ DEFINE_COMMAND_PLUGIN(ClearCustomMapMarker, , 0, 0, NULL);
 DEFINE_COMMAND_PLUGIN(EjectCasing, , 0, 2, kParams_EjectCasing);
 DEFINE_COMMAND_PLUGIN(SetHUDShudderPower, , 0, 1, kParams_OneFloat);
 DEFINE_COMMAND_PLUGIN(GetHUDShudderPower, , 0, 0, NULL);
+DEFINE_COMMAND_ALT_PLUGIN(SetMediaLocationControllerOverride, SetMLCOverride, , 0, 1, kParams_OneForm);
+DEFINE_COMMAND_ALT_PLUGIN(ClearMediaLocationControllerOverride, ClearMLCOverride, , 0, 0, NULL);
+DEFINE_COMMAND_ALT_PLUGIN(GetCasinoWinnings, , , 0, 1, kParams_OneCasino);
+DEFINE_COMMAND_ALT_PLUGIN(SetCasinoWinnings, , , 0, 2, kParams_OneCasinoOneInt);
+
 void(__cdecl* HandleActorValueChange)(ActorValueOwner* avOwner, int avCode, float oldVal, float newVal, ActorValueOwner* avOwner2) =
 (void(__cdecl*)(ActorValueOwner*, int, float, float, ActorValueOwner*))0x66EE50;
 bool(*Cmd_HighLightBodyPart)(COMMAND_ARGS) = (bool (*)(COMMAND_ARGS)) 0x5BB570;
@@ -67,6 +73,84 @@ void(__cdecl* HUDMainMenu_UpdateVisibilityState)(signed int) = (void(__cdecl*)(s
 
 std::unordered_map<TESForm*, std::pair<float, float>> tempEffectMap;
 
+bool __cdecl Cmd_SetCasinoWinnings_Execute(COMMAND_ARGS)
+{
+	TESCasino* casino;
+	SInt32 earnings;
+	if (ExtractArgs(EXTRACT_ARGS, &casino, &earnings) && casino)
+	{
+
+		auto casinoRefId = casino->refID;
+		auto iter = PlayerCharacter::GetSingleton()->casinoDataList->Head();
+		if (iter) {
+			do
+			{
+				if (auto casinoData = iter->data)
+				{
+					if (casinoData->casinoRefID == casinoRefId)
+					{
+						casinoData->earnings = earnings;
+						return true;
+					}
+				}
+			} while (iter = iter->next);
+		}
+
+		auto casinoStats = (CasinoStats*)GameHeapAlloc(sizeof(CasinoStats));
+		casinoStats->earningStage = 0;
+		casinoStats->earnings = earnings;
+		casinoStats->casinoRefID = casinoRefId;
+		PlayerCharacter::GetSingleton()->casinoDataList->Insert(casinoStats);
+	}
+
+	return true;
+}
+
+bool __cdecl Cmd_GetCasinoWinnings_Execute(COMMAND_ARGS)
+{
+	*result = 0;
+	TESCasino* casino = nullptr;
+	if (ExtractArgs(EXTRACT_ARGS, &casino) && casino)
+	{
+		auto casinoRefId = casino->refID;
+		auto iter = PlayerCharacter::GetSingleton()->casinoDataList->Head();
+		if (!iter) return true;
+		do
+		{ 
+			if (auto casinoData = iter->data)
+			{
+				if (casinoData->casinoRefID == casinoRefId)
+				{
+					*result = casinoData->earnings;
+					break;
+				}
+			}
+		} while (iter = iter->next);
+	}
+
+	return true;
+}
+
+bool Cmd_ClearMediaLocationControllerOverride_Execute(COMMAND_ARGS) {
+	*result = 0;
+	mlcOverridden = false;
+	mlcOverride = nullptr;
+	*result = 1;
+	
+	return true;
+}
+
+bool Cmd_SetMediaLocationControllerOverride_Execute(COMMAND_ARGS) {
+	*result = 0;
+	MediaLocationController* ctrl = NULL;
+	if (ExtractArgsEx(EXTRACT_ARGS_EX, &ctrl) && IS_TYPE(ctrl, MediaLocationController)) {
+		mlcOverridden = true;
+		mlcOverride = ctrl;
+		*result = 1;
+	}
+	return true;
+}
+
 bool Cmd_GetHUDShudderPower_Execute(COMMAND_ARGS) {
 	*result = 0;
 	UInt8 modId = scriptObj->GetModIndex();
diff --git a/nvse/nvse/GameForms.h b/nvse/nvse/GameForms.h
index ce9b37f..54aebbf 100644
--- a/nvse/nvse/GameForms.h
+++ b/nvse/nvse/GameForms.h
@@ -5990,3 +5990,11 @@ enum EWhichListForm {
 	eWhichListForm_FormList,
 	eWhichListForm_Max,
 };
+
+struct CasinoStats
+{
+	UInt32 casinoRefID;
+	SInt32 earnings;
+	UInt16 earningStage;
+	UInt8 gap0A[2];
+};
\ No newline at end of file
diff --git a/nvse/nvse/GameObjects.h b/nvse/nvse/GameObjects.h
index 2c58724..a7074f5 100644
--- a/nvse/nvse/GameObjects.h
+++ b/nvse/nvse/GameObjects.h
@@ -811,7 +811,7 @@ class PlayerCharacter : public Character {
 	TESObjectREFR* lastExteriorDoor;		// 604
 	void* unk608;				// 608
 	void* unk60C;				// 60C
-	void* unk610;				// 610
+	tList<CasinoStats>* casinoDataList;				// 610
 	tList<TESCaravanCard>* caravanCards1;			// 614
 	tList<TESCaravanCard>* caravanCards2;			// 618
 	UInt32								unk61C[7];				// 61C
diff --git a/nvse/nvse/ParamInfos.h b/nvse/nvse/ParamInfos.h
index a4444c8..c4406c1 100644
--- a/nvse/nvse/ParamInfos.h
+++ b/nvse/nvse/ParamInfos.h
@@ -831,4 +831,15 @@ static ParamInfo kParams_EjectCasing[2] =
 {
 	{	"Target Node",			kParamType_String,	1	},
 	{	"Custom Casing Path",	kParamType_String,  1	},
+};
+
+static ParamInfo kParams_OneCasino[1] =
+{
+	{    "Casino",    kParamType_Casino,    1    },
+};
+
+static ParamInfo kParams_OneCasinoOneInt[2] =
+{
+	{    "Casino",    kParamType_Casino,    1    },
+	{    "Earnings",    kParamType_Integer,    1    },
 };
\ No newline at end of file