require(GlobalDependencys:GetDependency("StandardBase"):GetPackageName())

--GAME VARS
fAdditionalFOV = 0
fAdditionalHelmetFOV = 0
fFOVMax = 110
fDefaultAspectRatio = 1.777777777
fDefaultAspectRatioHUD = 1.8

--ControlVars
bFOVFix = true
bHelmetFOV = true
bFixEnabled = true
bHUDFix = true

--PROCESS VARS
Process_FriendlyName = Module:GetFriendlyName()
Process_WindowName = "BioShock 2"
Process_ClassName = "Bioshock2UnrealWWindowsViewportWindow"
Process_EXEName = "*"

--INJECTION BEHAVIOUR
InjectDelay = 2500
WriteInterval = 100
SearchInterval = 500
SuspendThread = true

--Name                         Manual/Auto/Hybrid  		Steam/Origin/Any                IncludeFile:Configure;Enable;Periodic;Disable;
SupportedVersions = { 		
{"Automatically Detect",       "Hybrid",  			  	"Any",	                        "Configure_SignatureScan;Enable_Inject;Periodic;Disable_Inject;"},
}

function Init_Controls()
	DefaultControls.AddHeader("Header_FOV","FOV Fine adjustment",15,70,210,17)
	DefaultControls.AddFOVSlider("FOVSlider","FOVSlider_Changed",55,100,125,35)	
	DefaultControls.AddHeader("HelmetHeader_FOV","Helmet FOV Fine adjustment",15,162,210,17)
	DefaultControls.AddFOVSlider("HelmetFOVSlider","HelmetFOVSlider_Changed",55,192,125,35)	
	
	DefaultControls.AddHeader("Header_FixesEnableDisable","Individual Fixes",245,70,210,17)	
	DefaultControls.AddFixToggle("CKFOVFix_Enable","FOV Fix","CKFOVFix_Changed",255,101,180,14)
	DefaultControls.AddFixToggle("CKHelmetFOVFix_Enable","Helmet/Weapon FOV Fix","CKHelmetFOVFix_Changed",255,120,180,14)	
	DefaultControls.AddFixToggle("CKHUDFix_Enable","HUD Fix","CKHUDFix_Changed",255,139,180,14)
end

function Configure_SignatureScan() 

	local tAddress = HackTool:AddAddress("HUDFix")
	if HackTool:SignatureScan("D9????D9??????8B??????8B??????????E8",tAddress,PAGE_EXECUTE_READ,0x7,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )
	end		
	
	local tAddress = HackTool:AddAddress("AspectRatio")
	if HackTool:SignatureScan("D9 5C ?? ?? D9 44 ?? ?? DC 35 ?? ?? ?? ?? D8",tAddress,PAGE_EXECUTE_READ,0x8,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		tAddress:AcquireAddress(0x2)
		print( tAddress:GetInfo(TYPE_ADDRESS) )
		tAddress:AddSubOffset("EngineAspect",0*SIZE_DOUBLE)
		tAddress["EngineAspect"]:SetAutoUnprotect(true)
		tAddress:AddSubOffset("HelmetAspect",-1*SIZE_DOUBLE)	
		tAddress["HelmetAspect"]:SetAutoUnprotect(true)		
	end			
	
	
	local tAddress = HackTool:AddAddress("FOVFix")
	if HackTool:SignatureScan("8D ?? ?? ?? E9 ?? ?? ?? ?? D9 ?? ?? ?? ?? ?? 8B ?? ?? DD",tAddress,PAGE_EXECUTE_READ,0x9,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )		
	end		
	
	local tAddress = HackTool:AddAddress("FOVFixHelmet")
	if HackTool:SignatureScan("DC ?? D9 ?? D9 5C ?? ?? D8 ?? ?? ?? ?? ?? DE ?? D9 5C ?? ?? FF",tAddress,PAGE_EXECUTE_READ,0x8,Process_EXEName) == 0 then	
		return ErrorOccurred(string.format(SigScanError,tAddress:GetName()))
	else
		print( tAddress:GetInfo(TYPE_ADDRESS) )		
	end		

	return true

end


function Enable_Inject() 

	local Variables = HackTool:AllocateMemory("Variables",0)
	Variables:PushInt("HUDLeft")
	Variables:PushInt("HUDTop")
	Variables:PushInt("HUDWidth")
	Variables:PushInt("HUDHeight")
	Variables:Allocate()

	FOVCalculator1 = HackTool:InjectFOVCalculator("FOVCalculator1")
	FOVCalculator2 = HackTool:InjectFOVCalculator("FOVCalculator2")

	ResolutionChanged()
	
	local asm = [[	
	
		(codecave:jmp)HUDFix,HUDFix_cc:
			mov eax, [(allocation)Variables->HUDLeft]
			mov [$$2], eax									$context=1
			mov eax, [(allocation)Variables->HUDTop]		
			mov [$$2+04h], eax								$context=1
			mov eax, [(allocation)Variables->HUDWidth]
			mov [$$2+08h], eax								$context=1
			mov eax, [(allocation)Variables->HUDHeight]
			mov [$$2+0Ch], eax								$context=1
			%originalcode%
			jmp %returnaddress%		
			%end%	
			
		(codecave:jmp)FOVFix,FOVFix_cc:
			fld dword ptr [$$2]					$context=1
			call (allocation)FOVCalculator1		
			fstp dword ptr [$$2] 				$context=1
			%originalcode%
			jmp %returnaddress%
			%end%
			
		(codecave:jmp)FOVFixHelmet,FOVFixHelmet_cc:
			fld dword ptr [$$2]					$context=1
			call (allocation)FOVCalculator2	
			fstp dword ptr [$$2] 				$context=1
			%originalcode%
			jmp %returnaddress%
			%end%			

	]]

	if HackTool:CompileAssembly(asm,"FOVFixs") == nil then
		return ErrorOccurred("Assembly compilation failed...")
	else
		Toggle_CodeCave("FOVFix_cc",bFOVFix)
		Toggle_CodeCave("FOVFixHelmet_cc",bHelmetFOV)
		Toggle_CodeCave("HUDFix_cc",bHUDFix)
	end	
		
end

function Periodic()

	PluginViewport:AppendStatusMessage(	string.format("\r\n%s%s",FOVCalculatorSummary("FOVCalculator1","InGame",bFOVFix), 
										FOVCalculatorSummary("FOVCalculator2","Helmet",bHelmetFOV) )	)
	
	local Variables = HackTool:GetAllocation("Variables")	
	if Variables and bHUDFix == true then 								
		PluginViewport:AppendStatusMessage( string.format("\r\n     (HUDScaling) HUDLeft=%d, HUDTop=%d, HUDWidth=%d, HUDHeight=%d",
											Variables["HUDLeft"]:ReadInt(),Variables["HUDTop"]:ReadInt(),Variables["HUDWidth"]:ReadInt(),Variables["HUDHeight"]:ReadInt()))		
	end
	
	local AspectRatio = HackTool:GetAddress("AspectRatio")
	if AspectRatio then		
		AspectRatio["EngineAspect"]:WriteDouble(DisplayInfo:GetAspectRatio())
		AspectRatio["HelmetAspect"]:WriteDouble(DisplayInfo:GetAspectRatio())
	end
	
end

function Disable_Inject()
	CleanUp()
end

function ResolutionChanged() 
	
	UpdateFOVCalculator("FOVCalculator1",DisplayInfo:GetAspectRatio()/fDefaultAspectRatio,fAdditionalFOV)
	UpdateFOVCalculator("FOVCalculator2",DisplayInfo:GetAspectRatio()/fDefaultAspectRatioHUD,fAdditionalHelmetFOV)
	
	local Variables = HackTool:GetAllocation("Variables")
	if Variables and Variables["HUDLeft"] and Variables["HUDTop"] and Variables["HUDWidth"] and Variables["HUDHeight"] then
		Variables["HUDLeft"]:WriteInt(DisplayInfo:GetiOffsetX())
		Variables["HUDWidth"]:WriteInt(DisplayInfo:GetiOffsetWidth())
		Variables["HUDTop"]:WriteInt(DisplayInfo:GetiOffsetY())
		Variables["HUDHeight"]:WriteInt(DisplayInfo:GetiOffsetHeight())		
	end	

end

function CKFOVFix_Changed(Sender)

	bFOVFix = Toggle_CheckFix(Sender)
	Toggle_CodeCave("FOVFix_cc",bFOVFix)
	
end

function CKHelmetFOVFix_Changed(Sender)

	bHelmetFOV = Toggle_CheckFix(Sender)
	Toggle_CodeCave("FOVFixHelmet_cc",bHelmetFOV)
	
end

function CKHUDFix_Changed(Sender)

	bHUDFix = Toggle_CheckFix(Sender)
	Toggle_CodeCave("HUDFix_cc",bHUDFix)
	
end

function HK_IncreaseFOV()	
	FOVSlider:OffsetPosition(1)
end

function HK_DecreaseFOV()	
	FOVSlider:OffsetPosition(-1)
end

function FOVSlider_Changed(Sender)

	fAdditionalFOV = Sender:GetScaledFloat(5)
	UpdateFOVCalculator_AdditionalFOV("FOVCalculator1",fAdditionalFOV)
	lblFOVSlider.Caption:SetCaption( string.format("Value: %.2f",fAdditionalFOV) )
	
	ForceUpdate()	
		
end

function HelmetFOVSlider_Changed(Sender)

	fAdditionalHelmetFOV = Sender:GetScaledFloat(4)
	UpdateFOVCalculator_AdditionalFOV("FOVCalculator2",fAdditionalHelmetFOV)
	lblHelmetFOVSlider.Caption:SetCaption( string.format("Value: %.2f",fAdditionalHelmetFOV) )
	
	ForceUpdate()	
		
end

function Init()	
	Init_BaseControls()
	Init_Controls()
end

function DeInit()
	DisableFix()
end

