Merge pull request 'CatchUnitTesting' (#131) from CatchUnitTesting into master
Reviewed-on: #131
This commit is contained in:
commit
f7517a67e4
@ -1,7 +1,7 @@
|
||||
name: Emscripten Build
|
||||
run-name: Emscripten build initiated by ${{ gitea.actor }} for ${{ gitea.repository }}
|
||||
on: [push]
|
||||
|
||||
|
||||
jobs:
|
||||
Build_and_Deploy_Web_Build:
|
||||
runs-on: emscripten
|
||||
@ -18,10 +18,6 @@ jobs:
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y libfreetype6-dev
|
||||
- name: Build and Run Unit Tests
|
||||
run: |
|
||||
./test.sh
|
||||
./runTest.sh
|
||||
- name: Build Emscripten Project
|
||||
run: cmake --build ${{ gitea.event.repository.name }}/ -j 8
|
||||
- name: Move Files and Finalize
|
||||
@ -31,15 +27,35 @@ jobs:
|
||||
echo "Move files to final directory (/web/${{ gitea.event.repository.name }})"
|
||||
- name: Cleanup - Web Build Available
|
||||
run: echo "Emscripten build now available at http://projectdivar.com/files/web/${{ gitea.event.repository.name }}"
|
||||
- name: Send Webhook Update (Success)
|
||||
if: success()
|
||||
- name: Send Webhook Update
|
||||
if: always()
|
||||
run: |
|
||||
curl -k -v -X POST -H "Content-Type: application/json" \
|
||||
-d '{"action": "build_success", "repo": "${{ gitea.event.repository.name }}", "run_number":"${{ gitea.run_number }}"}' \
|
||||
-d '{"action": "build_result", "status": "${{ job.status }}", "ref": "${{ gitea.ref }}", "repo": "${{ gitea.event.repository.name }}", "run_number":"${{ gitea.run_number }}"}' \
|
||||
https://45.33.13.215:4505/postUpdate
|
||||
- name: Send Webhook Update (Failed)
|
||||
if: failure()
|
||||
UnitTesting:
|
||||
runs-on: gcc
|
||||
container:
|
||||
volumes:
|
||||
- /home/sigonasr2/assets:/assets
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y nodejs git libfreetype6-dev cmake
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: Build Unit Tests
|
||||
run: |
|
||||
./test.sh
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
pwd
|
||||
ln -s /assets "/workspace/AMay/AdventuresInLestoria/bin/assets"
|
||||
./runTest.sh
|
||||
- name: Send Webhook Update
|
||||
if: always()
|
||||
run: |
|
||||
curl -k -v -X POST -H "Content-Type: application/json" \
|
||||
-d '{"action": "build_fail", "repo": "${{ gitea.event.repository.name }}", "run_number":"${{ gitea.run_number }}"}' \
|
||||
-d '{"action": "test_result", "status": "${{ job.status }}", "ref": "${{ gitea.ref }}", "repo": "${{ gitea.event.repository.name }}", "run_number":"${{ gitea.run_number }}"}' \
|
||||
https://45.33.13.215:4505/postUpdate
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@ -425,8 +425,10 @@ desktop.ini
|
||||
/Adventures in Lestoria Tests/x64/Unit Testing
|
||||
/x64/Unit Testing
|
||||
/Adventures in Lestoria/assets/2.10
|
||||
/Adventures in Lestoria/assets/assets.zip
|
||||
/Adventures in Lestoria/assets/items/Bird_s Treasure.png
|
||||
|
||||
|
||||
tools
|
||||
/dotnet-tools.json
|
||||
/Adventures in Lestoria/assets.zip
|
||||
|
||||
@ -1,141 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{69757256-c088-4b22-9557-af7d281cee86}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="Shared" />
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(IncludePath)</IncludePath>
|
||||
<ExecutablePath>$(VC_ExecutablePath_x64);$(CommonExecutablePath);</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)../Adventures in Lestoria;;J:\AdventuresInLestoria\Adventures in Lestoria\steam;J:\AdventuresInLestoria\Adventures in Lestoria\discord-files</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalDependencies>discord_game_sdk.dll.lib;freetype.lib;steam_api64.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions>X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)../Adventures in Lestoria;$(ProjectDir)../Adventures in Lestoria;J:\AdventuresInLestoria\Adventures in Lestoria\steam;J:\AdventuresInLestoria\Adventures in Lestoria\discord-files</AdditionalIncludeDirectories>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<AdditionalDependencies>discord_game_sdk.dll.lib;freetype.lib;steam_api64.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="test.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Adventures in Lestoria\Adventures in Lestoria.vcxproj">
|
||||
<Project>{8e3067af-cfe7-4b11-bc6b-b867c32753d7}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1.8\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets" Condition="Exists('..\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1.8\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1.8\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1.8\build\native\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
Binary file not shown.
Binary file not shown.
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn" version="1.8.1.8" targetFramework="native" />
|
||||
</packages>
|
||||
@ -1,5 +0,0 @@
|
||||
//
|
||||
// pch.cpp
|
||||
//
|
||||
|
||||
#include "pch.h"
|
||||
@ -1,7 +0,0 @@
|
||||
//
|
||||
// pch.h
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
Binary file not shown.
@ -1,8 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "olcUTIL_Geometry2D.h"
|
||||
|
||||
using namespace olc::utils;
|
||||
|
||||
TEST(GeometryTest, CircleOverlapTest) {
|
||||
EXPECT_TRUE(geom2d::overlaps(geom2d::circle<float>{vf2d{},10},vf2d{5,5}));
|
||||
}
|
||||
@ -1,14 +1,12 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 18
|
||||
VisualStudioVersion = 18.4.11519.219 insiders
|
||||
VisualStudioVersion = 18.4.11519.219
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Adventures in Lestoria", "Adventures in Lestoria\Adventures in Lestoria.vcxproj", "{8E3067AF-CFE7-4B11-BC6B-B867C32753D7}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Adventures in Lestoria Tests", "Adventures in Lestoria Tests\Adventures in Lestoria Tests.vcxproj", "{11969B7B-3D50-4825-9584-AF01D15B88E0}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Adventures in Lestoria GTest", "Adventures in Lestoria GTest\Adventures in Lestoria GTest.vcxproj", "{69757256-C088-4B22-9557-AF7D281CEE86}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@ -60,33 +58,7 @@ Global
|
||||
{11969B7B-3D50-4825-9584-AF01D15B88E0}.Release|x64.ActiveCfg = Unit Testing|x64
|
||||
{11969B7B-3D50-4825-9584-AF01D15B88E0}.Release|x86.ActiveCfg = Unit Testing|Win32
|
||||
{11969B7B-3D50-4825-9584-AF01D15B88E0}.Unit Testing|x64.ActiveCfg = Unit Testing|x64
|
||||
{11969B7B-3D50-4825-9584-AF01D15B88E0}.Unit Testing|x64.Build.0 = Unit Testing|x64
|
||||
{11969B7B-3D50-4825-9584-AF01D15B88E0}.Unit Testing|x86.ActiveCfg = Unit Testing|Win32
|
||||
{11969B7B-3D50-4825-9584-AF01D15B88E0}.Unit Testing|x86.Build.0 = Unit Testing|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Debug|x64.Build.0 = Debug|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Debug|x86.Build.0 = Debug|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Emscripten Debug|x64.ActiveCfg = Release|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Emscripten Debug|x64.Build.0 = Release|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Emscripten Debug|x86.ActiveCfg = Release|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Emscripten Debug|x86.Build.0 = Release|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Emscripten|x64.ActiveCfg = Release|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Emscripten|x64.Build.0 = Release|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Emscripten|x86.ActiveCfg = Release|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Emscripten|x86.Build.0 = Release|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Release Desktop|x64.ActiveCfg = Release|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Release Desktop|x64.Build.0 = Release|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Release Desktop|x86.ActiveCfg = Release|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Release Desktop|x86.Build.0 = Release|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Release|x64.ActiveCfg = Release|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Release|x64.Build.0 = Release|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Release|x86.ActiveCfg = Release|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Release|x86.Build.0 = Release|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Unit Testing|x64.ActiveCfg = Release|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Unit Testing|x64.Build.0 = Release|x64
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Unit Testing|x86.ActiveCfg = Release|Win32
|
||||
{69757256-C088-4B22-9557-AF7D281CEE86}.Unit Testing|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
11
Adventures in Lestoria/.runsettings
Normal file
11
Adventures in Lestoria/.runsettings
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RunSettings>
|
||||
|
||||
<Catch2Adapter>
|
||||
<FilenameFilter>.*</FilenameFilter>
|
||||
<ExecutionMode>Single</ExecutionMode>
|
||||
<Logging>debug</Logging>
|
||||
<TestCaseTimeout>30000</TestCaseTimeout>
|
||||
</Catch2Adapter>
|
||||
|
||||
</RunSettings>
|
||||
@ -76,7 +76,9 @@
|
||||
"beach",
|
||||
"beach_boss",
|
||||
"undead_swamp",
|
||||
"undead_swamp_boss"
|
||||
"undead_swamp_boss",
|
||||
"foresty2",
|
||||
"mountain2"
|
||||
],
|
||||
"valuesAsFlags": false
|
||||
},
|
||||
|
||||
@ -77,7 +77,7 @@
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unit Testing|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v145</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
@ -145,7 +145,7 @@
|
||||
<CodeAnalysisRuleSet>..\CodeAnalysisRuleset.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unit Testing|x64'">
|
||||
<IncludePath>$(ProjectDir)include;$(VCInstallDir)Auxiliary\VS\UnitTest\include;$(IncludePath)</IncludePath>
|
||||
<IncludePath>$(ProjectDir)include;$(VCInstallDir)Auxiliary\VS\UnitTest\include;$(IncludePath);$(ProjectDir)</IncludePath>
|
||||
<LibraryPath>$(VCInstallDir)Auxiliary\VS\UnitTest\lib;$(LibraryPath)</LibraryPath>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<CodeAnalysisRuleSet>..\CodeAnalysisRuleset.ruleset</CodeAnalysisRuleSet>
|
||||
@ -251,7 +251,7 @@
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>UNIT_TESTING;OLC_PGE_HEADLESS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)steam;$(ProjectDir)discord-files;C:\Users\LabUser\source\repos\AdventuresInLestoria\Adventures in Lestoria\steam;C:\Users\LabUser\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\LabUser\Documents\include;C:\Users\niconiconii\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\niconiconii\OneDrive\Documents\include;C:\Users\niconiconii\source\repos\AdventuresInLestoria\Adventures in Lestoria\steam;C:\Users\sigon\source\repos\AdventuresInLestoria\Adventures in Lestoria\steam;C:\Users\sigon\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\sigon\OneDrive\Documents\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
@ -269,8 +269,7 @@
|
||||
<Command>powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h"</Command>
|
||||
</PreBuildEvent>
|
||||
<PostBuildEvent>
|
||||
<Command>
|
||||
</Command>
|
||||
<Command>powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File ../unit-testing-prebuild.ps1</Command>
|
||||
</PostBuildEvent>
|
||||
<Lib>
|
||||
<AdditionalDependencies>discord_game_sdk.dll.lib;freetype.lib;steam_api64.lib;$(CoreLibraryDependencies);%(AdditionalDependencies);</AdditionalDependencies>
|
||||
@ -411,6 +410,7 @@
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CastInfo.h" />
|
||||
<ClInclude Include="catch.h" />
|
||||
<ClInclude Include="DynamicMenuLabel.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
@ -421,6 +421,7 @@
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FriendlyType.h" />
|
||||
<ClInclude Include="GameHelper.h" />
|
||||
<ClInclude Include="HurtDamageInfo.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
@ -747,10 +748,6 @@
|
||||
<ClInclude Include="steam\steam_api_flat.h" />
|
||||
<ClInclude Include="steam\steam_api_internal.h" />
|
||||
<ClInclude Include="steam\steam_gameserver.h" />
|
||||
<ClInclude Include="TEST_DEFINES.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TextEntryLabel.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
@ -1095,6 +1092,33 @@
|
||||
</SubType>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Spider.cpp" />
|
||||
<ClCompile Include="tests\BuffTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\EffectTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\EnchantTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\EngineTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\FileTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\GeometryTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\ItemTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\MonsterTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\PlayerTests.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release Desktop|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ThunderOrb.cpp" />
|
||||
<ClCompile Include="TileGroup.cpp" />
|
||||
<ClCompile Include="Menu.cpp" />
|
||||
@ -1337,6 +1361,7 @@
|
||||
<None Include="..\runGame.bat" />
|
||||
<None Include="..\runGame.sh" />
|
||||
<None Include="..\unit-testing-prebuild.ps1" />
|
||||
<None Include=".runsettings" />
|
||||
<None Include="ClassDiagram.cd" />
|
||||
<None Include="ClassDiagram2.cd" />
|
||||
<None Include="cpp.hint" />
|
||||
@ -1344,6 +1369,7 @@
|
||||
<None Include="steam\steam_api.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\CMakeLists.txt" />
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\Accessories-test.txt" />
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\Equipment-test.txt" />
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\ItemDatabase-test.txt" />
|
||||
|
||||
@ -109,6 +109,12 @@
|
||||
<Filter Include="Configurations\Items\Test Configurations">
|
||||
<UniqueIdentifier>{354b389b-2ec1-4cf6-ace0-6597b14edfab}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\Unit Tests">
|
||||
<UniqueIdentifier>{38efdf17-2483-4a53-8598-e8cebb722137}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\Unit Testing">
|
||||
<UniqueIdentifier>{64d4cc9f-7c64-4939-9483-ddd2e3ad4bba}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="olcPixelGameEngine.h">
|
||||
@ -666,9 +672,6 @@
|
||||
<ClInclude Include="Pixel.h">
|
||||
<Filter>Header Files\Engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TEST_DEFINES.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Bullet.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -732,6 +735,12 @@
|
||||
<ClInclude Include="Effect.h">
|
||||
<Filter>Source Files\Effects</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="catch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GameHelper.h">
|
||||
<Filter>Header Files\Unit Testing</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Player.cpp">
|
||||
@ -1385,6 +1394,33 @@
|
||||
<ClCompile Include="Warrior.cpp">
|
||||
<Filter>Source Files\Player Classes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\BuffTests.cpp">
|
||||
<Filter>Source Files\Unit Tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\EffectTests.cpp">
|
||||
<Filter>Source Files\Unit Tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\EnchantTests.cpp">
|
||||
<Filter>Source Files\Unit Tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\EngineTests.cpp">
|
||||
<Filter>Source Files\Unit Tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\GeometryTests.cpp">
|
||||
<Filter>Source Files\Unit Tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\FileTests.cpp">
|
||||
<Filter>Source Files\Unit Tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\ItemTests.cpp">
|
||||
<Filter>Source Files\Unit Tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\MonsterTests.cpp">
|
||||
<Filter>Source Files\Unit Tests</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tests\PlayerTests.cpp">
|
||||
<Filter>Source Files\Unit Tests</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
@ -1451,6 +1487,7 @@
|
||||
<None Include="..\.gitea\workflows\emscripten_autobuild.yaml">
|
||||
<Filter>Configurations</Filter>
|
||||
</None>
|
||||
<None Include=".runsettings" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="InitialConcept.txt">
|
||||
@ -1674,6 +1711,7 @@
|
||||
<Filter>Documentation\Mechanics</Filter>
|
||||
</Text>
|
||||
<Text Include="Chapter_4_Boss.txt" />
|
||||
<Text Include="..\CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="assets\heart.ico">
|
||||
|
||||
@ -73,9 +73,11 @@ All rights reserved.
|
||||
#include "olcPGEX_Gamepad.h"
|
||||
#include "InventoryScrollableWindowComponent.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "discord.h"
|
||||
#include "steam/steam_api.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "GameSettings.h"
|
||||
#include "LoadingScreen.h"
|
||||
#include "Tutorial.h"
|
||||
@ -162,8 +164,10 @@ InputGroup AiL::KEY_MOUSE_RIGHT;
|
||||
InputGroup AiL::KEY_TOGGLE_MAP;
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
::discord::Core*Discord{};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
float AiL::SIZE_CHANGE_SPEED=1;
|
||||
|
||||
@ -294,8 +298,9 @@ void InitializeGameConfigurations(){
|
||||
bool AiL::OnUserCreate(){
|
||||
if(PACK_KEY=="INSERT_PACK_KEY_HERE"||PACK_KEY=="INSERT PACK KEY HERE")ERR("ERROR! Starting the game with the default pack ID is not allowed!");
|
||||
gamepack.LoadPack("assets/"+"gamepack_file"_S,PACK_KEY);
|
||||
|
||||
#ifndef OLC_PGE_HEADLESS
|
||||
GamePad::init();
|
||||
#endif
|
||||
Input::Initialize();
|
||||
|
||||
Font::init();
|
||||
@ -376,6 +381,7 @@ bool AiL::OnUserCreate(){
|
||||
)
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
if(steamKeyboardCallbackListener==nullptr){
|
||||
steamKeyboardCallbackListener=new SteamKeyboardCallbackHandler();
|
||||
}
|
||||
@ -383,13 +389,16 @@ bool AiL::OnUserCreate(){
|
||||
steamStatsReceivedHandlerListener=new SteamStatsReceivedHandler();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
utils::datafile::INITIAL_SETUP_COMPLETE=true;
|
||||
|
||||
ValidateGameStatus(); //Checks to make sure everything has been initialized properly.
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
SetupDiscord();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
player->InitializeMinimapImage();
|
||||
minimap.Initialize();
|
||||
@ -497,6 +506,7 @@ bool AiL::OnUserUpdate(float fElapsedTime){
|
||||
LoadingScreen::Draw();
|
||||
RenderVersionInfo();
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
if(Discord){
|
||||
auto result=Discord->RunCallbacks();
|
||||
if(result!=::discord::Result::Ok){
|
||||
@ -506,6 +516,7 @@ bool AiL::OnUserUpdate(float fElapsedTime){
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
skipGameProcess:
|
||||
@ -2688,6 +2699,9 @@ bool AiL::IsForegroundTile(TilesheetData sheet,int tileID){
|
||||
|
||||
const TilesheetData AiL::GetTileSheet(MapName map,int tileID)const{
|
||||
const std::vector<TilesetTag>&tileData=MAP_DATA.at(map).TilesetData;
|
||||
#ifdef UNIT_TESTING
|
||||
return{tileData[0].baseSourceDir,1,BLACK};
|
||||
#endif
|
||||
if(tileData.size()==1){
|
||||
return {tileData[0].baseSourceDir,1,MAP_TILESETS.at(tileData[0].baseSourceDir).tilecols[tileID]};
|
||||
}else{
|
||||
@ -2957,6 +2971,7 @@ datafiledoubledata AiL::GetDoubleList(std::string key){
|
||||
|
||||
bool Steam_Init(){
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
if(SteamAPI_Init()){
|
||||
if(SteamUtils()!=nullptr){
|
||||
SteamUtils()->SetWarningMessageHook([](int severity,const char*message){
|
||||
@ -2969,133 +2984,144 @@ bool Steam_Init(){
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(const int argn,char**args)
|
||||
{
|
||||
debugLogger.open("debug.log");
|
||||
LOG(std::format("Found {} args",argn));
|
||||
bool usingSteam=true;
|
||||
#ifdef UNIT_TESTING
|
||||
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
|
||||
#include "catch.h"
|
||||
|
||||
std::set_terminate([](){
|
||||
try{
|
||||
std::exception_ptr eptr{std::current_exception()};
|
||||
if(eptr)std::rethrow_exception(eptr);
|
||||
else std::cerr<<"Exiting without exception\n";
|
||||
}catch(const std::exception& ex){std::cerr<<"Exception: "<<ex.what()<< '\n';}
|
||||
catch(...){std::cerr << "Unknown exception caught\n";}
|
||||
#ifndef __EMSCRIPTEN__
|
||||
LOG(std::stacktrace::current());
|
||||
#endif
|
||||
std::exit(EXIT_FAILURE);
|
||||
});
|
||||
#else
|
||||
int main(const int argn,char**args)
|
||||
{
|
||||
debugLogger.open("debug.log");
|
||||
LOG(std::format("Found {} args",argn));
|
||||
bool usingSteam=true;
|
||||
|
||||
for(int i=0;i<argn;i++){
|
||||
if(std::string(args[i])=="nosteam"){
|
||||
LOG("nosteam flag detected. Disabling steam API...");
|
||||
usingSteam=false;
|
||||
}
|
||||
LOG(std::format("{}: {}",i,args[i]));
|
||||
}
|
||||
|
||||
if(!std::filesystem::exists("assets/config/configuration.txt")){
|
||||
ERR("WARNING! Could not find initial config file! Aborting.");
|
||||
return false;
|
||||
}
|
||||
{
|
||||
utils::datafile configFile;
|
||||
utils::datafile::Read(configFile,"assets/config/configuration.txt");
|
||||
usingSteam&=configFile["steam_api"].GetBool();
|
||||
if(usingSteam){
|
||||
std::set_terminate([](){
|
||||
try{
|
||||
std::exception_ptr eptr{std::current_exception()};
|
||||
if(eptr)std::rethrow_exception(eptr);
|
||||
else std::cerr<<"Exiting without exception\n";
|
||||
}catch(const std::exception& ex){std::cerr<<"Exception: "<<ex.what()<< '\n';}
|
||||
catch(...){std::cerr << "Unknown exception caught\n";}
|
||||
#ifndef __EMSCRIPTEN__
|
||||
if(!ADMIN_MODE&&SteamAPI_RestartAppIfNecessary(2895980U))return false; //Immediately quit if steam is detected and can be started through it.
|
||||
if(Steam_Init()){
|
||||
LOG("Steam API Initialized successfully!");
|
||||
}else{
|
||||
LOG("Steam API failed to initialize!");
|
||||
}
|
||||
#endif
|
||||
LOG(std::stacktrace::current());
|
||||
#endif
|
||||
std::exit(EXIT_FAILURE);
|
||||
});
|
||||
|
||||
for(int i=0;i<argn;i++){
|
||||
if(std::string(args[i])=="nosteam"){
|
||||
LOG("nosteam flag detected. Disabling steam API...");
|
||||
usingSteam=false;
|
||||
}
|
||||
LOG(std::format("{}: {}",i,args[i]));
|
||||
}
|
||||
}
|
||||
{
|
||||
InitializeGameConfigurations();
|
||||
AiL demo;
|
||||
|
||||
demo.UsingSteamAPI(usingSteam);
|
||||
|
||||
#pragma region Load Window Settings
|
||||
utils::datafile loadSystemFile;
|
||||
|
||||
std::string loadSystemFilename="save_file_path"_S+"system.conf";
|
||||
|
||||
vi2d windowPosConf={30,30};
|
||||
vi2d windowSizeConf=WINDOW_SIZE*4;
|
||||
bool fullscreenConf=false;
|
||||
bool vsyncConf=GameSettings::VSyncEnabled();
|
||||
|
||||
if(std::filesystem::exists(loadSystemFilename)){
|
||||
utils::datafile::Read(loadSystemFile,loadSystemFilename);
|
||||
if(loadSystemFile.HasProperty("Window Pos")){
|
||||
GameSettings::SetWindowPos({loadSystemFile["Window Pos"].GetInt(0),loadSystemFile["Window Pos"].GetInt(1)});
|
||||
windowPosConf={loadSystemFile["Window Pos"].GetInt(0),loadSystemFile["Window Pos"].GetInt(1)};
|
||||
}
|
||||
if(loadSystemFile.HasProperty("Window Size"))windowSizeConf={loadSystemFile["Window Size"].GetInt(0),loadSystemFile["Window Size"].GetInt(1)};
|
||||
size_t requiredSize=0;
|
||||
|
||||
#ifdef WIN32
|
||||
getenv_s(&requiredSize,NULL,0,"SteamTenfoot");
|
||||
#else
|
||||
const char*bigPicture=getenv("SteamTenfoot");
|
||||
if(bigPicture){
|
||||
requiredSize=strlen(bigPicture);
|
||||
LOG("Big Picture reported a length of "<<requiredSize);
|
||||
if(!std::filesystem::exists("assets/config/configuration.txt")){
|
||||
ERR("WARNING! Could not find initial config file! Aborting.");
|
||||
return false;
|
||||
}
|
||||
{
|
||||
utils::datafile configFile;
|
||||
utils::datafile::Read(configFile,"assets/config/configuration.txt");
|
||||
usingSteam&=configFile["steam_api"].GetBool();
|
||||
if(usingSteam){
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
if(!ADMIN_MODE&&SteamAPI_RestartAppIfNecessary(2895980U))return false; //Immediately quit if steam is detected and can be started through it.
|
||||
if(Steam_Init()){
|
||||
LOG("Steam API Initialized successfully!");
|
||||
}else{
|
||||
LOG("Steam API failed to initialize!");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
if(loadSystemFile.HasProperty("Fullscreen"))fullscreenConf=loadSystemFile["Fullscreen"].GetBool();
|
||||
if(loadSystemFile.HasProperty("VSync"))vsyncConf=loadSystemFile["VSync"].GetBool();
|
||||
if(requiredSize>0)fullscreenConf=true;
|
||||
}
|
||||
#pragma endregion
|
||||
}
|
||||
{
|
||||
InitializeGameConfigurations();
|
||||
AiL demo;
|
||||
|
||||
demo.UsingSteamAPI(usingSteam);
|
||||
|
||||
if (demo.Construct(windowPosConf.x, windowPosConf.y, windowSizeConf.x, windowSizeConf.y, WINDOW_SIZE.x, WINDOW_SIZE.y, 4, 4, fullscreenConf, vsyncConf))
|
||||
demo.Start();
|
||||
}
|
||||
#pragma region Load Window Settings
|
||||
utils::datafile loadSystemFile;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef __linux__
|
||||
HANDLE hLogFile;
|
||||
hLogFile = CreateFile(L"assets/memoryleak.txt", GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
_CrtSetReportMode(_CRT_WARN,_CRTDBG_MODE_FILE);
|
||||
_CrtSetReportFile(_CRT_WARN,hLogFile);
|
||||
_CrtDumpMemoryLeaks();
|
||||
CloseHandle(hLogFile);
|
||||
std::string loadSystemFilename="save_file_path"_S+"system.conf";
|
||||
|
||||
std::ifstream file("assets/memoryleak.txt");
|
||||
bool leaked=false;
|
||||
while(file.good()){
|
||||
std::string line;
|
||||
std::getline(file,line);
|
||||
if(line.find("AiL\\")!=std::string::npos){
|
||||
if(!leaked){
|
||||
leaked=true;
|
||||
LOG(std::endl<<std::endl<<std::endl<<"Memory leak detected!");
|
||||
}
|
||||
LOG(line);
|
||||
std::getline(file,line);
|
||||
LOG(line);
|
||||
}
|
||||
}
|
||||
if(leaked)ERR("")
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
vi2d windowPosConf={30,30};
|
||||
vi2d windowSizeConf=WINDOW_SIZE*4;
|
||||
bool fullscreenConf=false;
|
||||
bool vsyncConf=GameSettings::VSyncEnabled();
|
||||
|
||||
return 0;
|
||||
}
|
||||
if(std::filesystem::exists(loadSystemFilename)){
|
||||
utils::datafile::Read(loadSystemFile,loadSystemFilename);
|
||||
if(loadSystemFile.HasProperty("Window Pos")){
|
||||
GameSettings::SetWindowPos({loadSystemFile["Window Pos"].GetInt(0),loadSystemFile["Window Pos"].GetInt(1)});
|
||||
windowPosConf={loadSystemFile["Window Pos"].GetInt(0),loadSystemFile["Window Pos"].GetInt(1)};
|
||||
}
|
||||
if(loadSystemFile.HasProperty("Window Size"))windowSizeConf={loadSystemFile["Window Size"].GetInt(0),loadSystemFile["Window Size"].GetInt(1)};
|
||||
size_t requiredSize=0;
|
||||
|
||||
#ifdef WIN32
|
||||
getenv_s(&requiredSize,NULL,0,"SteamTenfoot");
|
||||
#else
|
||||
const char*bigPicture=getenv("SteamTenfoot");
|
||||
if(bigPicture){
|
||||
requiredSize=strlen(bigPicture);
|
||||
LOG("Big Picture reported a length of "<<requiredSize);
|
||||
}
|
||||
#endif
|
||||
if(loadSystemFile.HasProperty("Fullscreen"))fullscreenConf=loadSystemFile["Fullscreen"].GetBool();
|
||||
if(loadSystemFile.HasProperty("VSync"))vsyncConf=loadSystemFile["VSync"].GetBool();
|
||||
if(requiredSize>0)fullscreenConf=true;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
if (demo.Construct(windowPosConf.x, windowPosConf.y, windowSizeConf.x, windowSizeConf.y, WINDOW_SIZE.x, WINDOW_SIZE.y, 4, 4, fullscreenConf, vsyncConf))
|
||||
demo.Start();
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#ifndef __linux__
|
||||
HANDLE hLogFile;
|
||||
hLogFile = CreateFile(L"assets/memoryleak.txt", GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
_CrtSetReportMode(_CRT_WARN,_CRTDBG_MODE_FILE);
|
||||
_CrtSetReportFile(_CRT_WARN,hLogFile);
|
||||
_CrtDumpMemoryLeaks();
|
||||
CloseHandle(hLogFile);
|
||||
|
||||
std::ifstream file("assets/memoryleak.txt");
|
||||
bool leaked=false;
|
||||
while(file.good()){
|
||||
std::string line;
|
||||
std::getline(file,line);
|
||||
if(line.find("AiL\\")!=std::string::npos){
|
||||
if(!leaked){
|
||||
leaked=true;
|
||||
LOG(std::endl<<std::endl<<std::endl<<"Memory leak detected!");
|
||||
}
|
||||
LOG(line);
|
||||
std::getline(file,line);
|
||||
LOG(line);
|
||||
}
|
||||
}
|
||||
if(leaked)ERR("")
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _DEBUG
|
||||
#ifdef _WIN32
|
||||
@ -3228,8 +3254,10 @@ bool AiL::OnUserDestroy(){
|
||||
gameEnd=true;
|
||||
if(!savingFile){
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
SteamAPI_Shutdown();
|
||||
#endif
|
||||
#endif
|
||||
GFX.Reset();
|
||||
for(auto&map:MAP_DATA){
|
||||
if(map.optimizedTile!=nullptr){
|
||||
@ -3822,7 +3850,7 @@ const std::weak_ptr<Item>AiL::GetLoadoutItem(int slot){
|
||||
|
||||
void AiL::RestockLoadoutItems(){
|
||||
for(int slot=0;slot<GetLoadoutSize();slot++){
|
||||
if(!ISBLANK(GetLoadoutItem(slot))){
|
||||
if(!GetLoadoutItem(slot).expired()&&GetLoadoutItem(slot).lock()->it!=nullptr){
|
||||
SetLoadoutItem(slot,GetLoadoutItem(slot).lock()->ActualName());
|
||||
|
||||
//Set the loadout slot selection for this loadout item.
|
||||
@ -3907,7 +3935,7 @@ void AiL::SetLoadoutItem(int slot,std::string itemName){
|
||||
|
||||
bool AiL::UseLoadoutItem(int slot,const std::optional<vf2d>targetingPos){
|
||||
if(slot<0||slot>GetLoadoutSize()-1)ERR("Invalid inventory slot "+std::to_string(slot)+", please choose a slot in range (0-"+std::to_string(GetLoadoutSize()-1)+").");
|
||||
if(!ISBLANK(GetLoadoutItem(slot).lock())&&GetLoadoutItem(slot).lock()->Amt()>0){
|
||||
if(!ISBLANK(GetLoadoutItem(slot))&&GetLoadoutItem(slot).lock()->Amt()>0){
|
||||
Tutorial::GetTask(TutorialTaskName::USE_RECOVERY_ITEMS).I(A::ITEM_USE_COUNT)++;
|
||||
Inventory::UseItem(GetLoadoutItem(slot).lock()->ActualName(),1U,targetingPos);
|
||||
if(GameState::GetCurrentState()!=States::GAME_HUB){
|
||||
@ -4028,6 +4056,7 @@ void AiL::EndGame(){
|
||||
}
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
::discord::Result AiL::SetupDiscord(){
|
||||
auto result=::discord::Core::Create(1186719371750555780,DiscordCreateFlags_NoRequireDiscord,&Discord);
|
||||
if(result==::discord::Result::Ok){
|
||||
@ -4043,11 +4072,13 @@ void AiL::EndGame(){
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void AiL::UpdateDiscordStatus(std::string levelName,std::string className){
|
||||
std::string originalClassName=className;
|
||||
bool retry=false;
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
if(Discord){
|
||||
::discord::Activity newActivity{};
|
||||
newActivity.SetDetails(levelName.c_str());
|
||||
@ -4094,6 +4125,7 @@ void AiL::UpdateDiscordStatus(std::string levelName,std::string className){
|
||||
UpdateDiscordStatus(levelName,className);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void AiL::InitializePlayerLevelCap(){
|
||||
@ -4276,14 +4308,14 @@ const bool AiL::GameInitialized()const {
|
||||
|
||||
rcode AiL::LoadResource(Renderable&renderable,std::string_view imgPath,bool filter,bool clamp){
|
||||
rcode returnCode;
|
||||
if(gamepack.Loaded()){
|
||||
returnCode=renderable.Load(std::string(imgPath),&gamepack,filter,clamp);
|
||||
}else{
|
||||
returnCode=renderable.Load(std::string(imgPath),nullptr,filter,clamp);
|
||||
if("GENERATE_GAMEPACK"_B){
|
||||
gamepack.AddFile(std::string(imgPath));
|
||||
if(gamepack.Loaded()){
|
||||
returnCode=renderable.Load(std::string(imgPath),&gamepack,filter,clamp);
|
||||
}else{
|
||||
returnCode=renderable.Load(std::string(imgPath),nullptr,filter,clamp);
|
||||
if("GENERATE_GAMEPACK"_B){
|
||||
gamepack.AddFile(std::string(imgPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
|
||||
@ -49,8 +49,10 @@ All rights reserved.
|
||||
#include "olcUTIL_DataFile.h"
|
||||
#include "GameState.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "discord.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "Audio.h"
|
||||
#include "olcPGEX_SplashScreen.h"
|
||||
#include "olcPixelGameEngine.h"
|
||||
@ -60,6 +62,7 @@ All rights reserved.
|
||||
#include "Overlay.h"
|
||||
#include <variant>
|
||||
#include"safemap.h"
|
||||
#include"TileGroup.h"
|
||||
|
||||
#undef KEY_MENU
|
||||
#undef KEY_SELECT
|
||||
@ -448,8 +451,10 @@ private:
|
||||
//This function assigns the mode tile colors of each loaded tileset.
|
||||
void ComputeModeColors(TilesetData&tileset);
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
::discord::Result SetupDiscord();
|
||||
#endif
|
||||
#endif
|
||||
Audio audioEngine;
|
||||
SteamKeyboardCallbackHandler*steamKeyboardCallbackListener=nullptr;
|
||||
SteamStatsReceivedHandler*steamStatsReceivedHandlerListener=nullptr;
|
||||
@ -467,3 +472,8 @@ private:
|
||||
Pixel vignetteOverlayCol{"Interface.Vignette Color"_Pixel};
|
||||
std::vector<Notification>notifications;
|
||||
};
|
||||
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
#undef GetClassName
|
||||
@ -60,7 +60,8 @@ public:
|
||||
static void Update();
|
||||
static void UpdateLoop();
|
||||
static void Play(const std::string_view sound);
|
||||
[[nodiscard]]
|
||||
|
||||
|
||||
static const size_t LoadAndPlaySFX(const std::string_view sound,const bool loop=true);
|
||||
//Prepares a BGM for loading. This means we call UpdateLoop() repeatedly until the loading of the music is complete. Names are found in bgm.txt configuration file.
|
||||
static void PrepareBGM(const std::string_view sound,const bool loop=true);
|
||||
|
||||
@ -52,8 +52,10 @@ All rights reserved.
|
||||
#include "ProgressBar.h"
|
||||
#include "MenuItemLabel.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
#endif
|
||||
#include <bit>
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
@ -46,8 +46,10 @@ All rights reserved.
|
||||
#include "TextEntryLabel.h"
|
||||
#include "Checkbox.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "steam/isteamutils.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_DEMO_BUILD
|
||||
|
||||
@ -67,14 +67,8 @@ private:
|
||||
|
||||
using EffectData=EffectManager::EffectData;
|
||||
|
||||
|
||||
namespace EffectTests{
|
||||
class EffectTest;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct EffectRef{
|
||||
friend class EffectTests::EffectTest;
|
||||
public:
|
||||
inline EffectRef(int slotId,int effectId,bool foregroundEffect):slotId(slotId),effectId(effectId),foregroundEffect(foregroundEffect){}
|
||||
|
||||
@ -92,7 +86,11 @@ public:
|
||||
if(expired())ERR("WARNING! This effect was not properly checked for expiration! THIS IS NOT ALLOWED!");
|
||||
return dynamic_cast<T&>(EFF(*effectList.at(slotId).effect));
|
||||
};
|
||||
#ifndef UNIT_TESTING
|
||||
private:
|
||||
#else
|
||||
public:
|
||||
#endif
|
||||
int slotId;
|
||||
int effectId;
|
||||
bool foregroundEffect{false};
|
||||
|
||||
@ -58,14 +58,9 @@ enum class EffectType{
|
||||
BLIZZARD_SNOW,
|
||||
};
|
||||
|
||||
namespace EffectTests{
|
||||
class EffectTest;
|
||||
};
|
||||
|
||||
struct Effect{
|
||||
friend class AiL;
|
||||
friend struct FallingBullet;
|
||||
friend class EffectTests::EffectTest;
|
||||
vf2d pos={0,0};
|
||||
float lifetime=0;
|
||||
float fadeout=0;
|
||||
@ -100,7 +95,11 @@ protected:
|
||||
EffectType type{EffectType::NONE};
|
||||
Animate2D::Animation<std::string>animation;
|
||||
Animate2D::AnimationState internal_animState;
|
||||
#ifndef UNIT_TESTING
|
||||
private:
|
||||
#else
|
||||
public:
|
||||
#endif
|
||||
bool upperLevel=false;
|
||||
double aliveTime{};
|
||||
};
|
||||
|
||||
@ -10,9 +10,6 @@ INCLUDE_game
|
||||
debugLogger<<finalOutput.str()<<std::endl;
|
||||
std::cout<<finalOutput.str()<<std::endl;
|
||||
if(game&&game->ConsoleOut()&&game->ConsoleOut().good())game->ConsoleOut()<<finalOutput.str()<<std::endl;
|
||||
#ifdef UNITTESTING
|
||||
Logger::WriteMessage((finalOutput.str()+"\n").c_str());
|
||||
#endif
|
||||
}
|
||||
void Error::log(std::stringstream&str,std::source_location loc){
|
||||
std::stringstream finalOutput;
|
||||
@ -22,9 +19,6 @@ INCLUDE_game
|
||||
if(game&&game->ConsoleOut()&&game->ConsoleOut().good()){
|
||||
game->ConsoleOut()<<finalOutput.str()<<std::endl;
|
||||
}
|
||||
#ifdef UNITTESTING
|
||||
Logger::WriteMessage((finalOutput.str()+"\n").c_str());
|
||||
#endif
|
||||
throw std::runtime_error{finalOutput.str()};
|
||||
}
|
||||
#else
|
||||
|
||||
@ -38,7 +38,6 @@ All rights reserved.
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <strstream>
|
||||
#include <format>
|
||||
#include <any>
|
||||
#include <memory>
|
||||
@ -48,21 +47,19 @@ All rights reserved.
|
||||
#include <stacktrace>
|
||||
#endif
|
||||
#include<utility>
|
||||
#ifdef UNITTESTING
|
||||
#include "CppUnitTest.h"
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
#endif
|
||||
|
||||
inline std::ofstream debugLogger;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#ifndef __linux__
|
||||
#define NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ )
|
||||
// Replace _NORMAL_BLOCK with _CLIENT_BLOCK if you want the
|
||||
// allocations to be of _CLIENT_BLOCK type
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NEW //For everything else.
|
||||
|
||||
116
Adventures in Lestoria/GameHelper.h
Normal file
116
Adventures in Lestoria/GameHelper.h
Normal file
@ -0,0 +1,116 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#pragma once
|
||||
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include"catch.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
namespace Game{
|
||||
enum class CastWaitProperty{
|
||||
WAIT_FOR_CAST_TIME,
|
||||
NO_WAIT,
|
||||
};
|
||||
inline void Update(const float fElapsedTime){
|
||||
game->SetElapsedTime(fElapsedTime);
|
||||
game->OnUserUpdate(fElapsedTime);
|
||||
}
|
||||
inline void CastAbilityAtLocation(Ability&ability,const vf2d&worldLoc,const CastWaitProperty castWaitTime=CastWaitProperty::WAIT_FOR_CAST_TIME){ //NOTE: screenLoc is the actual screen coordinates, NOT the world coordinates! You are defining the mouse position essentially.
|
||||
game->GetPlayer()->SetTestScreenAimingLocation(worldLoc);
|
||||
game->GetPlayer()->PrepareCast(ability);
|
||||
game->GetPlayer()->CastSpell(ability);
|
||||
Game::Update(ability.precastInfo.castTime);
|
||||
}
|
||||
inline void ChangeClass(Player*&player_in,const Class&cl){
|
||||
game->ResetPlayerAndChangeClass(cl);
|
||||
player_in=game->GetPlayer();
|
||||
}
|
||||
inline std::weak_ptr<Item>GiveAndEquipEnchantedRing(const std::string_view enchantName,const EquipSlot slot=EquipSlot::RING1){
|
||||
std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)};
|
||||
Inventory::EquipItem(nullRing,slot);
|
||||
nullRing.lock()->_EnchantItem(enchantName);
|
||||
return nullRing;
|
||||
}
|
||||
//Adds the buff directly to the player instead of the buffs added list. (By calling an update tick.)
|
||||
inline void AddBuffToPlayer(BuffType type,float duration,float intensity){
|
||||
game->GetPlayer()->AddBuff(type,duration,intensity);
|
||||
Update(0.f);
|
||||
}
|
||||
//NOTE: If adding a % increase stat, please use the percentage version! 100% = 1!!
|
||||
inline void AddBuffToPlayer(BuffType type,float duration,float intensity,std::set<ItemAttribute>attr){
|
||||
game->GetPlayer()->AddBuff(type,duration,intensity,attr);
|
||||
Update(0.f);
|
||||
}
|
||||
//NOTE: If adding a % increase stat, please use the percentage version! 100% = 1!!
|
||||
inline void AddBuffToPlayer(BuffType type,float duration,float intensity,std::set<std::string>attr){
|
||||
game->GetPlayer()->AddBuff(type,duration,intensity,attr);
|
||||
Update(0.f);
|
||||
}
|
||||
|
||||
inline void ResetPlayerAndChangeClass(Class cl,Player*&pl,AiL*const game){
|
||||
game->ResetPlayerAndChangeClass(cl);
|
||||
pl=game->GetPlayer(); //The player pointer has been reassigned...
|
||||
}
|
||||
|
||||
inline void LoadLevelWithTMX(const std::string&mapKeyname,AiL*const game){
|
||||
game->InitializeLevel("map_path"_S+DATA["Levels"][mapKeyname]["Map File"].GetString(),mapKeyname);
|
||||
game->SetupLevel(game->MAP_DATA[mapKeyname]);
|
||||
_SetCurrentLevel(mapKeyname);
|
||||
}
|
||||
|
||||
inline void LoadFakeLevel(const std::string&mapKeyname,AiL*const game){
|
||||
game->MAP_DATA.at(mapKeyname).name=mapKeyname;
|
||||
game->SetupLevel(game->MAP_DATA[mapKeyname]);
|
||||
_SetCurrentLevel(mapKeyname);
|
||||
}
|
||||
|
||||
//NOTE: This will modify the currentLevel variable without triggering anything else in-game, this will normally mess up the state in the game. Ideally this is only used when initializing a test level.
|
||||
inline void _SetCurrentLevel(const MapName map){
|
||||
game->ResetLevelStates();
|
||||
game->currentLevel=map;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Test
|
||||
{
|
||||
template<class T>
|
||||
inline static void InRange(T initialVal,std::pair<T,T>range){
|
||||
REQUIRE((((initialVal)>=range.first)&&((initialVal)<=range.second)));
|
||||
}
|
||||
}
|
||||
@ -48,8 +48,10 @@ All rights reserved.
|
||||
#include "ClassInfo.h"
|
||||
#include "RowInventoryScrollableWindowComponent.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
#endif
|
||||
#include <ranges>
|
||||
#include "ItemEnchant.h"
|
||||
#include<algorithm>
|
||||
@ -675,11 +677,9 @@ uint32_t Item::Amt()const{
|
||||
return amt;
|
||||
};
|
||||
const std::string&Item::ActualName()const{
|
||||
if(_IsBlank())return BLANK_ITEM_NAME;
|
||||
return it->Name();
|
||||
};
|
||||
const std::string Item::DisplayName()const{
|
||||
if(_IsBlank())return BLANK_ITEM_NAME;
|
||||
std::string name=ActualName();
|
||||
if(IsEquippable()&&EnhancementLevel()>0){
|
||||
name+=" [#00FF00+"+std::to_string(EnhancementLevel())+"#FFFFFF]";
|
||||
|
||||
@ -167,14 +167,6 @@ public:
|
||||
const std::vector<std::pair<int,Stats>>&GetSetBonusBreakpoints()const;
|
||||
};
|
||||
|
||||
namespace PlayerTests{
|
||||
class PlayerTest;
|
||||
};
|
||||
|
||||
namespace EnchantTests{
|
||||
class EnchantTest;
|
||||
};
|
||||
|
||||
using IncreaseAmount=int;
|
||||
using RefineResult=std::pair<ItemAttribute,IncreaseAmount>;
|
||||
|
||||
@ -185,8 +177,6 @@ class Item{
|
||||
friend class SaveFile;
|
||||
friend void Merchant::PurchaseItem(IT item,uint32_t amt);
|
||||
friend void Merchant::SellItem(std::weak_ptr<Item>,uint32_t amt);
|
||||
friend class PlayerTests::PlayerTest;
|
||||
friend class EnchantTests::EnchantTest;
|
||||
public:
|
||||
static const std::string BLANK_ITEM_NAME;
|
||||
Item();
|
||||
@ -264,7 +254,11 @@ public:
|
||||
static const bool SelectedEquipIsDifferent(const std::weak_ptr<Item>equipAttemptingToEquip,const EquipSlot slotToEquipTo);
|
||||
static std::vector<std::string>GetItemCategories();
|
||||
const std::optional<std::string>&FragmentIcon()const;
|
||||
#ifndef UNIT_TESTING
|
||||
private:
|
||||
#else
|
||||
public:
|
||||
#endif
|
||||
//The amount in the current item stack.
|
||||
uint32_t amt;
|
||||
uint8_t enhancementLevel;
|
||||
@ -284,7 +278,6 @@ class Inventory{
|
||||
friend class Item;
|
||||
friend class SaveFile;
|
||||
friend class InventoryCreator;
|
||||
friend class ItemTests::ItemTest;
|
||||
public:
|
||||
|
||||
enum class DisassembleResult{
|
||||
@ -335,7 +328,11 @@ private:
|
||||
static std::multimap<IT,std::shared_ptr<Item>>_inventory;
|
||||
static std::vector<std::shared_ptr<Item>>blacksmithInventory;
|
||||
static std::map<EquipSlot,std::weak_ptr<Item>>equipment;
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
static std::array<std::pair<IT,int>,3U>loadoutItemsUsed;
|
||||
private:
|
||||
//Only contains "1" of every item, as this is a map to index items and not the actual storage of items!
|
||||
static std::map<ITCategory,std::vector<std::shared_ptr<Item>>>sortedInv;
|
||||
};
|
||||
|
||||
@ -39,10 +39,6 @@ All rights reserved.
|
||||
#include "util.h"
|
||||
#include "AdventuresInLestoria.h"
|
||||
|
||||
namespace MonsterTests{
|
||||
class MonsterTest;
|
||||
}
|
||||
|
||||
class ItemDrop{
|
||||
friend class AiL;
|
||||
vf2d pos;
|
||||
|
||||
@ -44,8 +44,6 @@ All rights reserved.
|
||||
|
||||
class ItemEnchantInfo{
|
||||
friend class ItemEnchant;
|
||||
friend class ItemTests::ItemTest;
|
||||
friend class PlayerTests::PlayerTest;
|
||||
public:
|
||||
enum class TextStyle{
|
||||
NORMAL,
|
||||
@ -108,7 +106,11 @@ private:
|
||||
ItemAttributable minStatModifiers;
|
||||
ItemAttributable maxStatModifiers;
|
||||
std::unordered_map<std::string,float>config;
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
static std::unordered_map<std::string,ItemEnchantInfo>ENCHANT_LIST;
|
||||
private:
|
||||
static std::unordered_map<ItemEnchantCategory,ItemEnchantCategoryData>ENCHANT_CATEGORIES;
|
||||
AbilityDescriptionModifiers modifiers;
|
||||
};
|
||||
|
||||
@ -63,6 +63,7 @@ std::vector<Steam::SteamInput>Input::rightStickActionSets{Steam::SCROLL};
|
||||
std::array<std::unordered_map<Steam::SteamInput,std::pair<std::string,HWButton>>,STEAM_INPUT_MAX_COUNT>Input::enumToActionName;
|
||||
std::unordered_map<EInputActionOrigin,std::string>Input::steamIconToGameIcon{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
{k_EInputActionOrigin_SteamController_A,"themes/button_d_xb.png"},
|
||||
{k_EInputActionOrigin_XBoxOne_A,"themes/button_d_xb.png"},
|
||||
{k_EInputActionOrigin_XBox360_A,"themes/button_d_xb.png"},
|
||||
@ -141,6 +142,7 @@ std::unordered_map<EInputActionOrigin,std::string>Input::steamIconToGameIcon{
|
||||
{k_EInputActionOrigin_SteamDeck_LeftStick_Move,"themes/button_analogstick.png"},
|
||||
{k_EInputActionOrigin_SteamDeck_RightStick_Move,"themes/button_analogstick.png"},
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
Input::Input(InputType type,int key)
|
||||
@ -178,6 +180,7 @@ void Input::Initialize(){
|
||||
void Input::LoadSteamButtonIcons(){
|
||||
GFX.Unlock();
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
for(int i=1;i<k_EInputActionOrigin_Count;i++){
|
||||
const char*imageName{SteamInput()->GetGlyphPNGForActionOrigin(EInputActionOrigin(i),k_ESteamInputGlyphSize_Small,0U)};
|
||||
if(imageName!=nullptr){
|
||||
@ -192,6 +195,7 @@ void Input::LoadSteamButtonIcons(){
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
GFX.SetInitialized();
|
||||
}
|
||||
|
||||
@ -913,6 +917,7 @@ const bool Input::HasExtendedIcons()const{
|
||||
const Renderable&Input::GetIcon()const{
|
||||
if(type==STEAM){
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
EInputActionOrigin action=Input::steamGameInputToOrigin.at(Steam::SteamInput(key)).second[0];
|
||||
EInputActionOrigin analogAction=Input::steamGameInputToAnalogOrigin.at(Steam::SteamInput(key)).second[0];
|
||||
if(Input::steamGameInputToOrigin.count(Steam::SteamInput(key))&&
|
||||
@ -932,6 +937,7 @@ const Renderable&Input::GetIcon()const{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return GFX.at(GenericKey::keyLiteral.at({type,key}).iconName);
|
||||
}
|
||||
@ -1118,31 +1124,35 @@ const bool Input::AxesActive(){
|
||||
}
|
||||
|
||||
void Input::StartVibration(const bool override){
|
||||
if(!GameSettings::RumbleEnabled(override))return;
|
||||
if(UsingGamepad()){
|
||||
STEAMINPUT(
|
||||
SteamInput()->TriggerVibration(steamControllers[activeSteamControllerIndex],std::numeric_limits<unsigned short>::max(),std::numeric_limits<unsigned short>::max());
|
||||
)else{
|
||||
for(GamePad*gamepad:GamePad::getGamepads()){
|
||||
if(gamepad->stillConnected){
|
||||
gamepad->startVibration();
|
||||
#ifndef OLC_PGE_HEADLESS
|
||||
if(!GameSettings::RumbleEnabled(override))return;
|
||||
if(UsingGamepad()){
|
||||
STEAMINPUT(
|
||||
SteamInput()->TriggerVibration(steamControllers[activeSteamControllerIndex],std::numeric_limits<unsigned short>::max(),std::numeric_limits<unsigned short>::max());
|
||||
)else{
|
||||
for(GamePad*gamepad:GamePad::getGamepads()){
|
||||
if(gamepad->stillConnected){
|
||||
gamepad->startVibration();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void Input::StopVibration(){
|
||||
STEAMINPUT(
|
||||
for(int i=0;i<controllerCount;i++){
|
||||
SteamInput()->TriggerVibration(steamControllers[i],0U,0U);
|
||||
}
|
||||
)else{
|
||||
for(GamePad*gamepad:GamePad::getGamepads()){
|
||||
if(gamepad->stillConnected){
|
||||
gamepad->stopVibration();
|
||||
#ifndef OLC_PGE_HEADLESS
|
||||
STEAMINPUT(
|
||||
for(int i=0;i<controllerCount;i++){
|
||||
SteamInput()->TriggerVibration(steamControllers[i],0U,0U);
|
||||
}
|
||||
)else{
|
||||
for(GamePad*gamepad:GamePad::getGamepads()){
|
||||
if(gamepad->stillConnected){
|
||||
gamepad->stopVibration();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const bool operator<(const InputGroup&group1,const InputGroup&group2){
|
||||
|
||||
@ -47,8 +47,10 @@ All rights reserved.
|
||||
#include "olcPGEX_ViewPort.h"
|
||||
#include "UndefKeys.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "steam/isteaminput.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "emscripten_compat.h"
|
||||
|
||||
class AiL;
|
||||
@ -149,10 +151,6 @@ public:
|
||||
static uint64_t ingameControlsHandle;
|
||||
};
|
||||
|
||||
namespace PlayerTests{
|
||||
class PlayerTest;
|
||||
}
|
||||
|
||||
class InputGroup{
|
||||
friend class AiL;
|
||||
friend class Menu;
|
||||
@ -160,7 +158,6 @@ class InputGroup{
|
||||
friend class InputListener;
|
||||
friend class SaveFile;
|
||||
friend class State_MainMenu;
|
||||
friend class PlayerTests::PlayerTest;
|
||||
std::set<Input>keys;
|
||||
std::vector<Input>keyOrder; //A list of keys inserted in order, for primary key mapping.
|
||||
static safemap<std::string,InputGroup*>menuNamesToInputGroups;
|
||||
|
||||
@ -91,9 +91,11 @@ void Menu::InitializeLoadGameWindow(){
|
||||
},ButtonAttr::FIT_TO_LABEL)END;
|
||||
onlineCharacterTab->SetSelectionType(HIGHLIGHT);
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
offlineCharacterTab->Disable();
|
||||
onlineCharacterTab->Disable();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#pragma region Keyboard Navigation Rules
|
||||
loadGameWindow->SetupKeyboardNavigation(
|
||||
|
||||
@ -123,7 +123,7 @@ class Menu:public IAttributable{
|
||||
friend class AiL;
|
||||
friend class ItemInfo;
|
||||
friend class EntityStats;
|
||||
friend class InputListener;
|
||||
friend class ::InputListener;
|
||||
|
||||
float buttonHoldTime=0;
|
||||
static vi2d lastActiveMousePos;
|
||||
|
||||
@ -49,8 +49,10 @@ All rights reserved.
|
||||
#include "SoundEffect.h"
|
||||
#include "Unlock.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "GameSettings.h"
|
||||
#include "ItemEnchant.h"
|
||||
#include <ranges>
|
||||
|
||||
@ -63,10 +63,6 @@ enum class Attribute;
|
||||
|
||||
class GameEvent;
|
||||
|
||||
namespace MonsterTests{
|
||||
class MonsterTest;
|
||||
};
|
||||
|
||||
class Entity;
|
||||
|
||||
class DeathSpawnInfo{
|
||||
@ -82,7 +78,6 @@ class Monster:public IAttributable{
|
||||
friend class AiL;
|
||||
friend class InventoryCreator;
|
||||
friend class DeathSpawnInfo;
|
||||
friend class MonsterTests::MonsterTest;
|
||||
friend struct MonsterData;
|
||||
friend const bool Entity::IsBoss()const;
|
||||
friend class Entity;
|
||||
@ -383,8 +378,14 @@ private:
|
||||
float targetAcquireTimer=0;
|
||||
vf2d spawnPos;
|
||||
int hp{0};
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
int mp{0};
|
||||
float mpRemainder{0.f};
|
||||
#ifdef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
ItemAttributable stats;
|
||||
float size;
|
||||
float attackCooldownTimer=0;
|
||||
@ -392,7 +393,13 @@ private:
|
||||
float z=0;
|
||||
float iframe_timer=0;
|
||||
Direction facingDirection;
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
std::string strategy;
|
||||
#ifdef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
State::State state=State::NORMAL;
|
||||
std::string overlaySprite="";
|
||||
uint8_t overlaySpriteTransparency=0U;
|
||||
@ -419,7 +426,13 @@ private:
|
||||
std::shared_ptr<DamageNumber>damageNumberPtr;
|
||||
std::shared_ptr<DamageNumber>dotNumberPtr;
|
||||
std::unordered_map<StrategyName,int>phase{}; //NOTE: THIS SHOULD NOT BE MODIFIED DIRECTLY!!! Use SetPhase(), GetPhase() / PHASE() SETPHASE() macros!
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
bool diesNormally=true; //If set to false, the monster death is handled in a special way. Set it to true when it's time to die.
|
||||
#ifdef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
float targetSize=0;
|
||||
bool isBoss=false;
|
||||
void OnDeath();
|
||||
@ -472,7 +485,13 @@ private:
|
||||
vf2d addedVel{};
|
||||
std::weak_ptr<Monster>attachedTarget; //A monster attached to another monster can then use this to alter behaviors based on the state of that other monster.
|
||||
float unconsciousTimer{};
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
const bool IsUnconscious()const;
|
||||
#ifdef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
const float UnconsciousTime()const;
|
||||
bool manualIgnoreTerrain{false}; //A manual flag that can be toggled on to dynamically make this monster ignore terrain collision.
|
||||
float collisionRadius{}; //The collision radius can be modified, it's just set initially to the monster database entry.
|
||||
|
||||
@ -70,12 +70,7 @@ struct MonsterAbilityData{
|
||||
std::optional<float>radius;
|
||||
};
|
||||
|
||||
namespace MonsterTests{
|
||||
class MonsterTest;
|
||||
};
|
||||
|
||||
struct MonsterData{
|
||||
friend class MonsterTests::MonsterTest;
|
||||
public:
|
||||
MonsterData();
|
||||
MonsterData(std::string name,std::string displayName,int hp,int atk,const uint32_t xp,std::vector<MonsterDropData>drops,float moveSpd=100.f,float size=1.0f,std::string strategy="Run Towards",int collisionDmg=0);
|
||||
@ -133,12 +128,24 @@ private:
|
||||
int hp;
|
||||
int atk;
|
||||
int startingMP{0};
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
float mpRecovery{0.f}; //In mana/sec
|
||||
#ifdef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
uint32_t xp;
|
||||
float moveSpd;//1.0=100%
|
||||
float size;
|
||||
std::unordered_set<std::string>animations;
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
std::vector<MonsterAbilityData>abilities{};
|
||||
#ifdef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
std::string displayName;
|
||||
std::string idleAnimation="WARRIOR_IDLE_S"; //Represents the basic animation name, not the full animation name that ANIMATION_DATA indexes into!! (Ex. Not GREEN_SLIME_IDLE, but IDLE)
|
||||
std::string jumpAnimation="WARRIOR_IDLE_S"; //Represents the basic animation name, not the full animation name that ANIMATION_DATA indexes into!! (Ex. Not GREEN_SLIME_JUMP, but JUMP)
|
||||
@ -146,7 +153,13 @@ private:
|
||||
std::string deathAnimation="WARRIOR_IDLE_S"; //Represents the basic animation name, not the full animation name that ANIMATION_DATA indexes into!! (Ex. Not GREEN_SLIME_DEATH, but DEATH)
|
||||
std::string strategy;
|
||||
int collisionDmg;
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
EventName hurtSound="";
|
||||
#ifdef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
EventName deathSound="";
|
||||
EventName walkSound="";
|
||||
std::vector<MonsterDropData> dropData;
|
||||
|
||||
@ -60,8 +60,10 @@ All rights reserved.
|
||||
|
||||
#include <ranges>
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
INCLUDE_MONSTER_DATA
|
||||
INCLUDE_MONSTER_LIST
|
||||
|
||||
@ -64,10 +64,6 @@ namespace MoveFlag{
|
||||
};
|
||||
};
|
||||
|
||||
namespace PlayerTest{
|
||||
class PlayerTests;
|
||||
}
|
||||
|
||||
class EntityStats{
|
||||
friend class Inventory;
|
||||
ItemAttributable equipStats; //The stats after gear calculations are applied.
|
||||
|
||||
@ -51,13 +51,7 @@ private:
|
||||
static std::unordered_set<size_t>playingSoundEffects;
|
||||
};
|
||||
|
||||
namespace MonsterTests{
|
||||
class MonsterTest;
|
||||
};
|
||||
|
||||
class SoundEffect{
|
||||
friend class PlayerTests::PlayerTest;
|
||||
friend class MonsterTests::MonsterTest;
|
||||
public:
|
||||
SoundEffect(const std::string_view filename,const float&vol,const float&minPitch=0.9f,const float&maxPitch=1.1f,const bool combatSound=false,const bool treatAsBGM=false);
|
||||
static void PlaySFX(const std::string&eventName,const vf2d&pos);
|
||||
@ -77,5 +71,11 @@ private:
|
||||
bool combatSound=false;
|
||||
float minPitch=0.9f;
|
||||
float maxPitch=1.1f;
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
inline static std::unordered_map<std::string,int>soundsPlayedLog{};
|
||||
#ifdef UNIT_TESTING
|
||||
private:
|
||||
#endif
|
||||
};
|
||||
@ -43,8 +43,10 @@ All rights reserved.
|
||||
#include "ItemDrop.h"
|
||||
#include "util.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
|
||||
@ -40,6 +40,7 @@ All rights reserved.
|
||||
#include "emscripten_compat.h"
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
void SteamKeyboardCallbackHandler::TextEntryComplete( GamepadTextInputDismissed_t* pCallback ){
|
||||
STEAMUTILS(
|
||||
if(pCallback->m_bSubmitted){
|
||||
@ -55,4 +56,5 @@ All rights reserved.
|
||||
}else Component<MenuComponent>(SAVE_FILE_NAME,"Back Button")->Click();
|
||||
)
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
@ -37,13 +37,17 @@ All rights reserved.
|
||||
#pragma endregion
|
||||
#pragma once
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "steam/steam_api.h"
|
||||
#endif
|
||||
#endif
|
||||
#include <string>
|
||||
#include "TextEntryLabel.h"
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
class SteamKeyboardCallbackHandler{
|
||||
STEAM_CALLBACK(SteamKeyboardCallbackHandler,TextEntryComplete,GamepadTextInputDismissed_t);
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
@ -45,10 +45,12 @@ All rights reserved.
|
||||
INCLUDE_DATA
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
void SteamStatsReceivedHandler::SteamStatsReceived( UserStatsReceived_t* pCallback ){
|
||||
if(pCallback->m_eResult==k_EResultOK){
|
||||
SteamUserStats()->GetStat("Achievement.Kill Unlocks.Total Kill API Name"_S.c_str(),&Unlock::monsterKillCount);
|
||||
LOG(std::format("Retrieved monster kill count: {}",Unlock::monsterKillCount));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -37,11 +37,15 @@ All rights reserved.
|
||||
#pragma endregion
|
||||
#pragma once
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "steam/steam_api.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
class SteamStatsReceivedHandler{
|
||||
STEAM_CALLBACK(SteamStatsReceivedHandler,SteamStatsReceived,UserStatsReceived_t);
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
@ -1,46 +0,0 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#pragma once
|
||||
|
||||
namespace PlayerTests{
|
||||
class PlayerTest;
|
||||
}
|
||||
|
||||
namespace ItemTests{
|
||||
class ItemTest;
|
||||
}
|
||||
@ -123,14 +123,6 @@ struct NPCData{
|
||||
NPCData(XMLTag npcTag);
|
||||
};
|
||||
|
||||
namespace MonsterTests{
|
||||
class MonsterTest;
|
||||
}
|
||||
|
||||
namespace ItemTests{
|
||||
class ItemTest;
|
||||
}
|
||||
|
||||
namespace Game{
|
||||
void LoadFakeLevel(const std::string&mapKeyname,AiL*const game);
|
||||
};
|
||||
@ -138,7 +130,6 @@ namespace Game{
|
||||
struct Map{
|
||||
friend class AiL;
|
||||
friend class TMXParser;
|
||||
friend class ItemTests::ItemTest;
|
||||
friend void Game::LoadFakeLevel(const std::string&mapKeyname,AiL*const game);
|
||||
enum class MapType{
|
||||
DUNGEON,
|
||||
@ -156,7 +147,11 @@ private:
|
||||
std::vector<EnvironmentalAudio>environmentalAudioData;
|
||||
std::vector<ItemMapData>stageLoot;
|
||||
std::vector<NPCData>npcs;
|
||||
#ifdef UNIT_TESTING
|
||||
public:
|
||||
#endif
|
||||
MapType mapType{};
|
||||
private:
|
||||
std::string bgmSongName="";
|
||||
std::string audioEvent{"Default Volume"};
|
||||
std::unordered_map<Class,float>devCompletionTrialTime;
|
||||
|
||||
@ -34,6 +34,10 @@ Qty Up/Down is finicky
|
||||
Add item icons in crafting menu descriptions
|
||||
HP Recovery can be too much
|
||||
|
||||
Make molotov bigger
|
||||
|
||||
Item quantity inside the item box
|
||||
|
||||
In-universe explanation of item sets
|
||||
Battle Cry movement speed buff?
|
||||
Add potential upgrade amount on description before upgrading
|
||||
@ -43,6 +47,16 @@ Collect loadout items in field = add to count immediately?
|
||||
|
||||
Crafting equipment should take you back to the item you were at.
|
||||
|
||||
No damage / No loadout items used / Defeat All
|
||||
- On repeats
|
||||
- Incentives for bonus XP
|
||||
|
||||
Crab contact damage is high
|
||||
|
||||
Warrior Shield bash
|
||||
|
||||
Bug in objects in stages? (1-1 bridge)
|
||||
|
||||
|
||||
DEMO
|
||||
====
|
||||
|
||||
@ -38,7 +38,6 @@ All rights reserved.
|
||||
#include "Map.h"
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "safemap.h"
|
||||
#include"TileGroupDataFile.h"
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
|
||||
@ -1 +1,22 @@
|
||||
#pragma once
|
||||
#include"olcUTIL_Geometry2D.h"
|
||||
|
||||
struct TileGroup{
|
||||
friend class TileGroupDataFile;
|
||||
private:
|
||||
geom2d::rect<int>range;
|
||||
geom2d::rect<float>collisionRange={{},{}};
|
||||
std::vector<TileRenderData>tiles;
|
||||
int minX=0,minY=0,maxX=0,maxY=0;
|
||||
public:
|
||||
static float FADE_TIME;
|
||||
//0-255. 255 indicates fully invisible.
|
||||
static uint8_t FADE_AMT;
|
||||
geom2d::rect<float>GetCollisionRange();
|
||||
geom2d::rect<int>GetRange();
|
||||
//The fade range is the bounds in which this tile group will be considered "in range" of a player, one tile in each direction further than its actual range.
|
||||
geom2d::rect<int>GetFadeRange();
|
||||
std::vector<TileRenderData>&GetTiles();
|
||||
void InsertTile(TileRenderData tile);
|
||||
float fadeFactor=0.f;
|
||||
};
|
||||
@ -46,26 +46,6 @@ All rights reserved.
|
||||
INCLUDE_PACK_KEY
|
||||
INCLUDE_game
|
||||
|
||||
struct TileGroup{
|
||||
friend class TileGroupDataFile;
|
||||
private:
|
||||
geom2d::rect<int>range;
|
||||
geom2d::rect<float>collisionRange={{},{}};
|
||||
std::vector<TileRenderData>tiles;
|
||||
int minX=0,minY=0,maxX=0,maxY=0;
|
||||
public:
|
||||
static float FADE_TIME;
|
||||
//0-255. 255 indicates fully invisible.
|
||||
static uint8_t FADE_AMT;
|
||||
geom2d::rect<float>GetCollisionRange();
|
||||
geom2d::rect<int>GetRange();
|
||||
//The fade range is the bounds in which this tile group will be considered "in range" of a player, one tile in each direction further than its actual range.
|
||||
geom2d::rect<int>GetFadeRange();
|
||||
std::vector<TileRenderData>&GetTiles();
|
||||
void InsertTile(TileRenderData tile);
|
||||
float fadeFactor=0.f;
|
||||
};
|
||||
|
||||
enum TileReadTag:uint32_t{
|
||||
TILESET_NAME,
|
||||
FIRSTGID,
|
||||
|
||||
@ -42,8 +42,10 @@ All rights reserved.
|
||||
#include "DEFINES.h"
|
||||
#include "emscripten_compat.h"
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifndef UNIT_TESTING
|
||||
#include "steam/isteamuserstats.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
INCLUDE_DATA
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 13349
|
||||
#define VERSION_BUILD 13532
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
||||
Binary file not shown.
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<map version="1.10" tiledversion="1.11.0" class="Map" orientation="orthogonal" renderorder="right-down" width="192" height="156" tilewidth="24" tileheight="24" infinite="0" nextlayerid="8" nextobjectid="109">
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="192" height="156" tilewidth="24" tileheight="24" infinite="0" nextlayerid="8" nextobjectid="109">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty1_1"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty2"/>
|
||||
<property name="Level Type" type="int" propertytype="LevelType" value="0"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="../maps/Tilesheet_No_Shadow24x24.tsx"/>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="200" height="122" tilewidth="24" tileheight="24" infinite="0" nextlayerid="10" nextobjectid="83">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty1_1"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty2"/>
|
||||
<property name="Level Type" type="int" propertytype="LevelType" value="0"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="../maps/Tilesheet_No_Shadow24x24.tsx"/>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="245" height="275" tilewidth="24" tileheight="24" infinite="0" nextlayerid="7" nextobjectid="70">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="mountain_day"/>
|
||||
<property name="Background Music" propertytype="BGM" value="mountain"/>
|
||||
<property name="Background Music" propertytype="BGM" value="mountain2"/>
|
||||
<property name="Level Type" type="int" propertytype="LevelType" value="0"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="../maps/Tilesheet_No_Shadow24x24.tsx"/>
|
||||
|
||||
@ -6,12 +6,12 @@ WORLD_MAP = 2026-02-27 21:53:33.6568368
|
||||
CAMPAIGN_1_1 = 2026-01-21 20:30:58.3723266
|
||||
BOSS_1_B = 2024-09-13 21:28:58.8886132
|
||||
BOSS_2 = 2026-01-21 20:30:58.4312572
|
||||
BOSS_3 = 2026-04-13 20:07:59.9982330
|
||||
BOSS_3_B = 2026-04-21 02:50:32.8922615
|
||||
BOSS_3 = 2026-04-23 20:04:39.8919861
|
||||
BOSS_3_B = 2026-04-23 20:04:39.8919861
|
||||
CAMPAIGN_7_1 = 2024-09-13 21:28:58.8570782
|
||||
CAMPAIGN_1_4 = 2024-09-13 21:41:17.0083532
|
||||
CAMPAIGN_1_4 = 2026-04-28 20:00:03.4806604
|
||||
BOSS_2_B = 2026-01-21 20:30:58.4322614
|
||||
CAMPAIGN_1_2 = 2026-01-21 20:30:58.3736269
|
||||
CAMPAIGN_1_2 = 2026-04-28 19:44:26.2017819
|
||||
CAMPAIGN_1_3 = 2024-09-13 21:28:58.8532684
|
||||
CAMPAIGN_1_5 = 2024-09-13 21:28:58.8557772
|
||||
CAMPAIGN_4_8 = 2026-02-26 21:44:13.5419545
|
||||
@ -21,10 +21,10 @@ CAMPAIGN_1_B1 = 2024-09-13 21:28:58.8605592
|
||||
CAMPAIGN_1_8 = 2024-09-13 21:28:58.8595553
|
||||
CAMPAIGN_4_5 = 2026-02-26 21:44:13.5315825
|
||||
CAMPAIGN_2_1 = 2026-01-21 20:30:58.3756334
|
||||
CAMPAIGN_2_2 = 2026-01-21 20:30:58.3769261
|
||||
CAMPAIGN_2_3 = 2026-04-13 20:04:48.1801993
|
||||
CAMPAIGN_2_2 = 2026-04-28 19:44:26.2126272
|
||||
CAMPAIGN_2_3 = 2026-04-23 20:04:39.8896736
|
||||
CAMPAIGN_2_4 = 2026-01-21 20:30:58.3804324
|
||||
CAMPAIGN_2_5 = 2026-04-22 02:07:26.4326535
|
||||
CAMPAIGN_2_5 = 2026-04-23 20:04:39.8906724
|
||||
CAMPAIGN_2_6 = 2026-01-21 20:30:58.3836104
|
||||
CAMPAIGN_2_7 = 2026-01-21 20:30:58.3846135
|
||||
CAMPAIGN_2_8 = 2026-01-21 20:30:58.3866133
|
||||
@ -38,7 +38,7 @@ CAMPAIGN_3_5 = 2026-01-21 20:30:58.3977329
|
||||
CAMPAIGN_3_6 = 2026-01-21 20:30:58.4008008
|
||||
CAMPAIGN_3_7 = 2026-01-21 20:30:58.4023071
|
||||
CAMPAIGN_3_8 = 2026-01-21 20:30:58.4049027
|
||||
CAMPAIGN_3_B1 = 2026-04-21 02:50:32.8922615
|
||||
CAMPAIGN_3_B1 = 2026-04-23 20:04:39.8919861
|
||||
CAMPAIGN_4_1 = 2026-04-13 18:08:48.5353335
|
||||
CAMPAIGN_4_2 = 2026-02-26 21:44:13.5210572
|
||||
CAMPAIGN_4_4 = 2026-02-26 21:44:13.5270745
|
||||
|
||||
@ -20,6 +20,24 @@ BGM
|
||||
}
|
||||
}
|
||||
|
||||
#Song title followed by filenames for individual parts
|
||||
foresty2
|
||||
{
|
||||
Track Name = Foresty 2
|
||||
|
||||
channel[0]=commercial_assets/foresty2.ogg
|
||||
|
||||
# Transition time between one phase to the next.
|
||||
Fade Time = 2.0
|
||||
|
||||
Loop Repeat Start Point = 0.0s
|
||||
|
||||
Events
|
||||
{
|
||||
Default Volume = 70%
|
||||
}
|
||||
}
|
||||
|
||||
#Song title followed by filenames for individual parts
|
||||
overworld
|
||||
{
|
||||
|
||||
Binary file not shown.
17999
Adventures in Lestoria/catch.h
Normal file
17999
Adventures in Lestoria/catch.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,3 +16,4 @@ _N"; std::string class::idle_e="WARRIOR_IDLE_E"; std::string class::idle_s="WARR
|
||||
#define INCLUDE_ITEM_DATA
|
||||
#define INCLUDE_LEVEL_NAMES
|
||||
#define INCLUDE_GFX
|
||||
#define TEST(cl, testCaseName) TEST_CASE_METHOD(cl,"["#cl"] "##testCaseName)
|
||||
|
||||
@ -13,6 +13,22 @@ class GamepadTextInputDismissed_t{};
|
||||
|
||||
inline void SteamAPI_RunCallbacks(){};
|
||||
|
||||
#define STEAMINPUT(statement) if(false){}
|
||||
#define STEAMUTILS(statement) if(false){}
|
||||
#define STEAMUSERSTATS(statement) if(false){}
|
||||
#else
|
||||
#ifdef UNIT_TESTING
|
||||
#define STEAM_INPUT_MAX_COUNT 0
|
||||
#define STEAM_INPUT_MAX_ORIGINS 0
|
||||
#define STEAM_CALLBACK(arg1,arg2,arg3)
|
||||
enum EInputActionOrigin{};
|
||||
using InputHandle_t=uint64_t;
|
||||
using InputActionSetHandle_t=uint64_t;
|
||||
|
||||
class GamepadTextInputDismissed_t{};
|
||||
|
||||
inline void SteamAPI_RunCallbacks(){};
|
||||
|
||||
#define STEAMINPUT(statement) if(false){}
|
||||
#define STEAMUTILS(statement) if(false){}
|
||||
#define STEAMUSERSTATS(statement) if(false){}
|
||||
@ -21,3 +37,4 @@ inline void SteamAPI_RunCallbacks(){};
|
||||
#define STEAMUTILS(statement) if(SteamUtils()){statement}
|
||||
#define STEAMUSERSTATS(statement) if(SteamUserStats()){statement}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -280,7 +280,9 @@ namespace olc {
|
||||
|
||||
static void enumerateGamepads();
|
||||
static GamePad *openGamepad(const std::string &path);
|
||||
#ifndef OLC_PGE_HEADLESS
|
||||
static X11::Display *display;
|
||||
#endif
|
||||
static std::optional<int> inotifyFd;
|
||||
|
||||
constexpr static const int32_t buttonCodes[GP_BUTTON_COUNT]{BTN_X,
|
||||
@ -318,6 +320,7 @@ namespace olc {
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#ifndef UNIT_TESTING
|
||||
#ifdef OLC_PGE_GAMEPAD
|
||||
#undef OLC_PGE_GAMEPAD
|
||||
|
||||
@ -1403,4 +1406,165 @@ std::vector<olc::GamePad *> olc::GamePad::gamepads;
|
||||
|
||||
#endif // OLC_PGE_GAMEPAD
|
||||
|
||||
#pragma endregion
|
||||
#pragma endregion
|
||||
#else
|
||||
#ifdef OLC_PGE_GAMEPAD
|
||||
#undef OLC_PGE_GAMEPAD
|
||||
#pragma region Platform Dependent
|
||||
|
||||
#pragma region Windows
|
||||
#ifdef WIN32
|
||||
BOOL IsXInputDevice(const GUID *pGuidProductFromDirectInput) {
|
||||
return false;
|
||||
}
|
||||
void olc::GamePad::init() {}
|
||||
|
||||
void olc::GamePad::updateGamepads() {}
|
||||
|
||||
inline olc::GamePad::GamePad(LPCDIDEVICEINSTANCEA lpddi) {}
|
||||
|
||||
inline olc::GamePad::GamePad(DWORD xId) : xId(xId), xInput(true) {}
|
||||
|
||||
void olc::GamePad::poll() {}
|
||||
|
||||
void olc::GamePad::startVibration(float strength) const {}
|
||||
|
||||
void olc::GamePad::stopVibration() const {}
|
||||
|
||||
olc::GamePad::~GamePad() {}
|
||||
|
||||
std::string olc::GamePad::getId() {return {};}
|
||||
|
||||
#endif
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Linux
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
olc::GamePad *olc::GamePad::openGamepad(const std::string &path) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create a gamepad from a path to the event file
|
||||
olc::GamePad::GamePad(std::string path, int fd)
|
||||
: path{std::move(path)}, availableAxes{false},
|
||||
availableButtons{false}, effect{}, fd{fd} {
|
||||
|
||||
}
|
||||
|
||||
bool olc::GamePad::readEvent(input_event &event) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
void olc::GamePad::poll() {
|
||||
}
|
||||
|
||||
void olc::GamePad::updateGamepads() {
|
||||
}
|
||||
|
||||
void olc::GamePad::enumerateGamepads() {
|
||||
}
|
||||
|
||||
std::string olc::GamePad::getId() { return {}; }
|
||||
|
||||
void olc::GamePad::startVibration(float strength) const {}
|
||||
|
||||
void olc::GamePad::stopVibration() const {
|
||||
}
|
||||
|
||||
olc::GamePad::~GamePad() {
|
||||
}
|
||||
|
||||
void olc::GamePad::reconnect() {
|
||||
}
|
||||
|
||||
void olc::GamePad::init() {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
olc::GamePad::GamePad(long id, std::string name) : name{name}, id{id} {}
|
||||
|
||||
void olc::GamePad::poll() {
|
||||
}
|
||||
|
||||
void olc::GamePad::updateGamepads() { }
|
||||
|
||||
std::string olc::GamePad::getId() { return {}; }
|
||||
|
||||
void olc::GamePad::startVibration(float strength) const {}
|
||||
|
||||
void olc::GamePad::stopVibration() const {}
|
||||
|
||||
olc::GamePad::~GamePad() {}
|
||||
|
||||
void olc::GamePad::init() {
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Common
|
||||
|
||||
olc::GamePad *olc::GamePad::selectWithButton(olc::GPButtons b) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
olc::GamePad *olc::GamePad::selectWithAnyButton() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float olc::GamePad::getAxis(olc::GPAxes a) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const float olc::GamePad::getDeadZone()const{
|
||||
return {};
|
||||
}
|
||||
const float olc::GamePad::getDeadZoneOuter()const{
|
||||
return {};
|
||||
}
|
||||
|
||||
void olc::GamePad::setDeadZone(const float deadZone){
|
||||
}
|
||||
void olc::GamePad::setDeadZoneOuter(const float deadZoneOuter){
|
||||
}
|
||||
|
||||
olc::HWButton olc::GamePad::getButton(olc::GPButtons b) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string olc::GamePad::getName() { return {}; }
|
||||
|
||||
int olc::GamePad::getAxisCount() const { return {}; }
|
||||
|
||||
int olc::GamePad::getButtonCount() const { return {}; }
|
||||
|
||||
void olc::GamePad::handleButton(int id, bool value) {
|
||||
}
|
||||
|
||||
bool olc::GamePad::hasAxis(GPAxes a) { return {}; }
|
||||
|
||||
bool olc::GamePad::hasButton(GPButtons b) {
|
||||
return {};
|
||||
}
|
||||
|
||||
bool olc::GamePad::OnBeforeUserUpdate(float &fElapsedTime) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<olc::GamePad *> &olc::GamePad::getGamepads() { return gamepads; }
|
||||
|
||||
std::vector<olc::GamePad *> olc::GamePad::gamepads;
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#endif // OLC_PGE_GAMEPAD
|
||||
|
||||
#pragma endregion
|
||||
#endif
|
||||
@ -41,6 +41,7 @@ All rights reserved.
|
||||
#include "olcUTIL_Geometry2D.h"
|
||||
#include "olcPixelGameEngine.h"
|
||||
|
||||
#ifndef UNIT_TESTING
|
||||
#ifdef WIN32
|
||||
#include <ft2build.h>
|
||||
#pragma comment(lib, "freetype.lib")
|
||||
@ -57,6 +58,7 @@ All rights reserved.
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "Error.h"
|
||||
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
|
||||
@ -484,4 +486,79 @@ FT_Library olc::Font::library;
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
namespace olc {
|
||||
struct FontRect {
|
||||
olc::vi2d offset;
|
||||
olc::vi2d size;
|
||||
};
|
||||
|
||||
class Font : public olc::PGEX {
|
||||
public:
|
||||
Font() = default;
|
||||
|
||||
~Font() {
|
||||
}
|
||||
|
||||
Font(std::string path, int fontSize){
|
||||
}
|
||||
|
||||
Font(const Font &other) = delete;
|
||||
Font(Font &&other)noexcept{ }
|
||||
|
||||
Font &operator=(const Font &other) = delete;
|
||||
Font &operator=(Font &&other)noexcept{
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
FontRect _GetStringBounds(std::u32string string, float angle = 0.0f) {
|
||||
return olc::FontRect{};
|
||||
}
|
||||
|
||||
public:
|
||||
FontRect GetStringBounds(std::u32string string, float angle = 0.0f) {
|
||||
return {};
|
||||
}
|
||||
|
||||
olc::Sprite *RenderStringToSprite(std::u32string string,
|
||||
olc::Pixel color) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
olc::Decal *RenderStringToDecal(std::u32string string,
|
||||
olc::Pixel color) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
olc::Renderable RenderStringToRenderable(std::u32string string,
|
||||
olc::Pixel color) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void AddFallbackFont(std::string path) {
|
||||
}
|
||||
|
||||
std::u32string GetFontName(){
|
||||
return {};
|
||||
}
|
||||
|
||||
static bool init() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void DrawBitmap(int x, int y, int bmp, int color) {
|
||||
}
|
||||
void DrawBitmapTo(int x, int y, int bmp, int color,
|
||||
int *sprite) {
|
||||
}
|
||||
|
||||
uint8_t GetCharIndex(char32_t charCode) {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
} // namespace olc
|
||||
#endif
|
||||
#endif
|
||||
@ -377,7 +377,9 @@ return 0;
|
||||
*/
|
||||
#pragma endregion
|
||||
|
||||
#ifndef OLC_PGE_HEADLESS
|
||||
#define OLC_GFX_OPENGL33
|
||||
#endif
|
||||
|
||||
#ifndef OLC_PGE_DEF
|
||||
#define OLC_PGE_DEF
|
||||
@ -409,7 +411,6 @@ return 0;
|
||||
#include "olcUTIL_Geometry2D.h"
|
||||
#include "Pixel.h"
|
||||
#include "util.h"
|
||||
#include "TEST_DEFINES.h"
|
||||
#pragma endregion
|
||||
|
||||
#define PGE_VER 225
|
||||
@ -1699,6 +1700,10 @@ namespace olc
|
||||
olc::rcode Sprite::LoadFromFile(const std::string& sImageFile, olc::ResourcePack* pack)
|
||||
{
|
||||
UNUSED(pack);
|
||||
if(!loader){
|
||||
util::GetCaseInsensitiveFilename(sImageFile);
|
||||
return olc::rcode::OK;
|
||||
}
|
||||
return loader->LoadImageResource(this, util::GetCaseInsensitiveFilename(sImageFile), pack);
|
||||
}
|
||||
|
||||
@ -5359,6 +5364,9 @@ namespace olc
|
||||
virtual olc::rcode SetWindowTitle(const std::string& s) { return olc::rcode::OK; }
|
||||
virtual olc::rcode StartSystemEventLoop() { return olc::rcode::OK; }
|
||||
virtual olc::rcode HandleSystemEvent() { return olc::rcode::OK; }
|
||||
virtual olc::rcode SetFullscreen(const bool bFullscreen, const vi2d windowPos = {}){return olc::rcode::OK;}
|
||||
virtual void SetWindowPos(vi2d pos){}
|
||||
virtual void SetWindowSize(vi2d size){}
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -54,6 +54,9 @@ David Barr, aka javidx9, <20>OneLoneCoder 2019, 2020, 2021, 2022
|
||||
#pragma once
|
||||
#include "olcUTIL_Geometry2D.h"
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
namespace olc::utils
|
||||
{
|
||||
class Camera2D
|
||||
@ -216,6 +219,7 @@ namespace olc::utils
|
||||
|
||||
case Mode::LazyFollow:
|
||||
{
|
||||
#undef min
|
||||
m_vPosition += (GetTarget() - m_vPosition) * std::min(1.f,m_fLazyFollowRate * fElapsedTime);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -61,10 +61,10 @@ David Barr, aka javidx9, <20>OneLoneCoder 2019, 2020, 2021, 2022
|
||||
#include <fstream>
|
||||
#include <stack>
|
||||
#include <sstream>
|
||||
#include <strstream>
|
||||
#include <numeric>
|
||||
#include "Error.h"
|
||||
#include<ranges>
|
||||
#include"util.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
|
||||
@ -2498,4 +2498,6 @@ namespace olc::utils::geom2d
|
||||
}
|
||||
|
||||
using namespace olc;
|
||||
using namespace olc::utils;
|
||||
using namespace olc::utils;
|
||||
#undef min
|
||||
#undef max
|
||||
187
Adventures in Lestoria/tests/BuffTests.cpp
Normal file
187
Adventures in Lestoria/tests/BuffTests.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "config.h"
|
||||
#include "ItemDrop.h"
|
||||
#include "Tutorial.h"
|
||||
#include "DamageNumber.h"
|
||||
#include "GameHelper.h"
|
||||
#include"catch.h"
|
||||
|
||||
using namespace olc::utils;
|
||||
|
||||
INCLUDE_INITIALIZEGAMECONFIGURATIONS
|
||||
INCLUDE_game
|
||||
INCLUDE_GFX
|
||||
INCLUDE_DAMAGENUMBER_LIST
|
||||
|
||||
class BuffTests{
|
||||
public:
|
||||
inline BuffTests(){
|
||||
SetupTestMonster();
|
||||
SetupMockMap();
|
||||
}
|
||||
inline ~BuffTests(){
|
||||
testGame->EndGame();
|
||||
testGame->OnUserUpdate(0.f);
|
||||
testGame.reset();
|
||||
}
|
||||
std::unique_ptr<AiL>testGame;
|
||||
#pragma region Setup Functions
|
||||
void SetupTestMonster(){
|
||||
InitializeGameConfigurations();
|
||||
testGame.reset(new AiL(true));
|
||||
ItemAttribute::Initialize();
|
||||
ItemInfo::InitializeItems();
|
||||
testGame->InitializeGraphics();
|
||||
testGame->InitializeClasses();
|
||||
sig::Animation::InitializeAnimations();
|
||||
testGame->InitializeDefaultKeybinds();
|
||||
testGame->InitializePlayer();
|
||||
sig::Animation::SetupPlayerAnimations();
|
||||
Menu::InitializeMenus();
|
||||
Tutorial::Initialize();
|
||||
Stats::InitializeDamageReductionTable();
|
||||
Monster::InitializeStrategies();
|
||||
|
||||
GameState::Initialize();
|
||||
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
|
||||
testGame->ResetLevelStates();
|
||||
|
||||
#pragma region Setup a fake test map
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
Game::_SetCurrentLevel("CAMPAIGN_1_1");
|
||||
ItemDrop::ClearDrops();
|
||||
#pragma endregion
|
||||
|
||||
MonsterData testMonsterData{"TestName","Test Monster",30,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
MONSTER_DATA["TestName"]=testMonsterData;
|
||||
|
||||
Menu::themes.SetInitialized();
|
||||
GFX.SetInitialized();
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
void SetupMockMap(){
|
||||
game->MAP_DATA.at("CAMPAIGN_1_1")=Map{};
|
||||
ItemDrop::ClearDrops();
|
||||
}
|
||||
#pragma endregion
|
||||
};
|
||||
|
||||
TEST(BuffTests,"AddBuffMonsterCallbackExpireFunctionTest"){
|
||||
Monster&m{game->SpawnMonster({},MONSTER_DATA.at("TestName"))};
|
||||
Game::Update(0.f);
|
||||
REQUIRE(size_t(0)==m.GetBuffs(BuffType::AFFECTED_BY_LIGHTNING_BOLT).size());
|
||||
m.AddBuff(BuffType::AFFECTED_BY_LIGHTNING_BOLT,3.f,1,[](std::weak_ptr<Monster>attachedTarget,Buff&b){attachedTarget.lock()->Hurt(5,attachedTarget.lock()->OnUpperLevel(),attachedTarget.lock()->GetZ());});
|
||||
REQUIRE(size_t(1)==m.GetBuffs(BuffType::AFFECTED_BY_LIGHTNING_BOLT).size());
|
||||
Game::Update(0.f);
|
||||
Game::Update(3.f);
|
||||
REQUIRE(25==m.GetHealth());
|
||||
}
|
||||
|
||||
TEST(BuffTests,"AddBuffPlayerCallbackExpireFunctionTest"){
|
||||
REQUIRE(size_t(0)==game->GetPlayer()->GetBuffs(BuffType::AFFECTED_BY_LIGHTNING_BOLT).size());
|
||||
game->GetPlayer()->AddBuff(BuffType::AFFECTED_BY_LIGHTNING_BOLT,3.f,1,[](Player*attachedTarget,Buff&b){attachedTarget->Hurt(5,attachedTarget->OnUpperLevel(),attachedTarget->GetZ());});
|
||||
Game::Update(0.f);
|
||||
REQUIRE(size_t(1)==game->GetPlayer()->GetBuffs(BuffType::AFFECTED_BY_LIGHTNING_BOLT).size());
|
||||
Game::Update(0.f);
|
||||
Game::Update(3.f);
|
||||
REQUIRE(95==game->GetPlayer()->GetHealth());
|
||||
}
|
||||
TEST(BuffTests,"MonsterHasBuffFunctionTest"){
|
||||
Monster&m{game->SpawnMonster({},MONSTER_DATA.at("TestName"))};
|
||||
Game::Update(0.f);
|
||||
REQUIRE(!m.HasBuff(BuffType::SPEEDBOOST));
|
||||
m.AddBuff(BuffType::ADRENALINE_RUSH,1.f,1.f);
|
||||
REQUIRE(!m.HasBuff(BuffType::SPEEDBOOST));
|
||||
m.AddBuff(BuffType::SPEEDBOOST,1.f,1.f);
|
||||
REQUIRE(m.HasBuff(BuffType::SPEEDBOOST));
|
||||
m.AddBuff(BuffType::SPEEDBOOST,2.f,1.f);
|
||||
REQUIRE(m.HasBuff(BuffType::SPEEDBOOST));
|
||||
Game::Update(0.f);
|
||||
Game::Update(1.f);
|
||||
REQUIRE(m.HasBuff(BuffType::SPEEDBOOST));
|
||||
Game::Update(1.f);
|
||||
REQUIRE(!m.HasBuff(BuffType::SPEEDBOOST));
|
||||
m.AddBuff(BuffType::SPEEDBOOST,1.f,1.f);
|
||||
m.RemoveBuff(BuffType::SPEEDBOOST);
|
||||
REQUIRE(!m.HasBuff(BuffType::SPEEDBOOST));
|
||||
}
|
||||
TEST(BuffTests,"PlayerHasBuffFunctionTest"){
|
||||
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
|
||||
Game::AddBuffToPlayer(BuffType::ADRENALINE_RUSH,1.f,1.f);
|
||||
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
|
||||
Game::AddBuffToPlayer(BuffType::SPEEDBOOST,1.f,1.f);
|
||||
REQUIRE(game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
|
||||
Game::AddBuffToPlayer(BuffType::SPEEDBOOST,2.f,1.f);
|
||||
REQUIRE(game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
|
||||
Game::Update(0.f);
|
||||
Game::Update(1.f);
|
||||
REQUIRE(game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
|
||||
Game::Update(1.f);
|
||||
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
|
||||
Game::AddBuffToPlayer(BuffType::SPEEDBOOST,1.f,1.f);
|
||||
game->GetPlayer()->RemoveBuff(BuffType::SPEEDBOOST);
|
||||
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
|
||||
}
|
||||
TEST(BuffTests,"PlayerDoesNotImmediatelyReceiveBuffTest"){
|
||||
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
|
||||
game->GetPlayer()->AddBuff(BuffType::SPEEDBOOST,1.f,1.f);
|
||||
REQUIRE(!game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
|
||||
Game::Update(0.f);
|
||||
REQUIRE(game->GetPlayer()->HasBuff(BuffType::SPEEDBOOST));
|
||||
}
|
||||
|
||||
TEST(BuffTests,"MonsterGetBuffFunctionTest"){
|
||||
Monster&m{game->SpawnMonster({},MONSTER_DATA.at("TestName"))};
|
||||
Game::Update(0.f);
|
||||
REQUIRE(!bool(m.GetBuff(BuffType::ADRENALINE_RUSH)));
|
||||
m.AddBuff(BuffType::ADRENALINE_RUSH,1.f,1.f);
|
||||
m.AddBuff(BuffType::SPEEDBOOST,1.f,1.f);
|
||||
m.AddBuff(BuffType::SPEEDBOOST,2.f,1.f);
|
||||
Game::Update(0.f);
|
||||
REQUIRE(bool(m.GetBuff(BuffType::ADRENALINE_RUSH)));
|
||||
REQUIRE(bool(m.GetBuff(BuffType::SPEEDBOOST)));
|
||||
REQUIRE(1.f==(*m.GetBuff(BuffType::SPEEDBOOST)).lifetime);
|
||||
Game::Update(1.f);
|
||||
REQUIRE(1.f==(*m.GetBuff(BuffType::SPEEDBOOST)).lifetime);
|
||||
Game::Update(1.f);
|
||||
REQUIRE(!bool(m.GetBuff(BuffType::SPEEDBOOST)));
|
||||
}
|
||||
208
Adventures in Lestoria/tests/EffectTests.cpp
Normal file
208
Adventures in Lestoria/tests/EffectTests.cpp
Normal file
@ -0,0 +1,208 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "Tutorial.h"
|
||||
#include <random>
|
||||
#include "ItemDrop.h"
|
||||
#include"SoundEffect.h"
|
||||
#include"GameHelper.h"
|
||||
#include"catch.h"
|
||||
|
||||
using namespace olc::utils;
|
||||
|
||||
INCLUDE_GFX
|
||||
INCLUDE_ITEM_DATA
|
||||
INCLUDE_DAMAGENUMBER_LIST
|
||||
INCLUDE_INITIALIZEGAMECONFIGURATIONS
|
||||
INCLUDE_MONSTER_LIST
|
||||
|
||||
extern std::mt19937 rng;
|
||||
|
||||
class EffectTests{
|
||||
public:
|
||||
std::unique_ptr<AiL>testGame;
|
||||
InputGroup testKeyboardInput;
|
||||
Player*player;
|
||||
HWButton*testKey;
|
||||
inline EffectTests(){
|
||||
InitializeGameConfigurations();
|
||||
rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run.
|
||||
testGame.reset(new AiL(true));
|
||||
ItemAttribute::Initialize();
|
||||
ItemInfo::InitializeItems();
|
||||
testGame->InitializeGraphics();
|
||||
testGame->InitializeClasses();
|
||||
sig::Animation::InitializeAnimations();
|
||||
testGame->InitializeDefaultKeybinds();
|
||||
testGame->InitializePlayer();
|
||||
sig::Animation::SetupPlayerAnimations();
|
||||
Menu::InitializeMenus();
|
||||
Tutorial::Initialize();
|
||||
Stats::InitializeDamageReductionTable();
|
||||
Monster::InitializeStrategies();
|
||||
SoundEffect::Initialize();
|
||||
|
||||
GameState::Initialize();
|
||||
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
|
||||
ItemDrop::Initialize();
|
||||
testGame->ResetLevelStates();
|
||||
|
||||
#pragma region Setup a fake test map and test monster
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
game->MAP_DATA.at("CAMPAIGN_1_1")._SetMapData(MapTag{24*24,24*24,24,24});
|
||||
ItemDrop::ClearDrops();
|
||||
MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
MONSTER_DATA["TestName"]=testMonsterData;
|
||||
#pragma endregion
|
||||
|
||||
testGame->InitializeCamera();
|
||||
|
||||
player=testGame->GetPlayer();
|
||||
//Setup key "0" as a test input
|
||||
testKeyboardInput.AddKeybind(Input{InputType::KEY,0});
|
||||
testKey=testGame->GetKeyboardState(0);
|
||||
testGame->olc_UpdateKeyFocus(true); //Force the game to be "focused" for tests. Required if we want keyboard inputs to work.
|
||||
testKey->bHeld=true; //Assume key is held for every test unless otherwise needs to be changed.
|
||||
Menu::themes.SetInitialized();
|
||||
GFX.SetInitialized();
|
||||
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
inline ~EffectTests(){
|
||||
testGame->EndGame();
|
||||
testGame->OnUserUpdate(0.f);
|
||||
testGame.reset();
|
||||
}
|
||||
};
|
||||
TEST(EffectTests,"EffectListsStartEmpty"){
|
||||
REQUIRE(size_t(0)==EffectManager::GetBackgroundEffectCount());
|
||||
REQUIRE(size_t(0)==EffectManager::GetForegroundEffectCount());
|
||||
}
|
||||
TEST(EffectTests,"EffectListCountsAdjustWhenAddingAndRemovingEffects"){
|
||||
REQUIRE(size_t(0)==EffectManager::GetBackgroundEffectCount());
|
||||
REQUIRE(size_t(0)==EffectManager::GetForegroundEffectCount());
|
||||
const auto&foregroundEffRef{game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f})};
|
||||
REQUIRE(size_t(1)==EffectManager::GetForegroundEffectCount());
|
||||
REQUIRE(size_t(0)==EffectManager::GetBackgroundEffectCount());
|
||||
REQUIRE(0==foregroundEffRef.slotId);
|
||||
REQUIRE(0==foregroundEffRef.effectId);
|
||||
REQUIRE(true==foregroundEffRef.foregroundEffect);
|
||||
REQUIRE(false==foregroundEffRef.expired());
|
||||
const auto&foregroundEffRef2{game->AddEffect(Effect{vf2d{},1.f,"pixel.png",false,0.f,0.5f})};
|
||||
const auto&backgroundEffRef{game->AddEffect(Effect{vf2d{},1.f,"pixel.png",false,0.f},true)};
|
||||
REQUIRE(size_t(2)==EffectManager::GetForegroundEffectCount());
|
||||
REQUIRE(size_t(1)==EffectManager::GetBackgroundEffectCount());
|
||||
REQUIRE(0==backgroundEffRef.slotId);
|
||||
REQUIRE(2==backgroundEffRef.effectId);
|
||||
REQUIRE(false==backgroundEffRef.foregroundEffect);
|
||||
REQUIRE(false==backgroundEffRef.expired());
|
||||
REQUIRE(false==foregroundEffRef2.expired());
|
||||
Game::Update(0.5f);
|
||||
REQUIRE(size_t(1)==EffectManager::GetForegroundEffectCount());
|
||||
REQUIRE(size_t(1)==EffectManager::GetBackgroundEffectCount());
|
||||
REQUIRE(true==foregroundEffRef.expired());
|
||||
REQUIRE(false==foregroundEffRef2.expired());
|
||||
Game::Update(0.5f);
|
||||
REQUIRE(size_t(1)==EffectManager::GetForegroundEffectCount());
|
||||
REQUIRE(size_t(0)==EffectManager::GetBackgroundEffectCount());
|
||||
const auto&foregroundEffRef3{game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f})};
|
||||
REQUIRE(size_t(2)==EffectManager::GetForegroundEffectCount());
|
||||
REQUIRE(size_t(0)==EffectManager::GetBackgroundEffectCount());
|
||||
REQUIRE(0==foregroundEffRef3.slotId);
|
||||
REQUIRE(3==foregroundEffRef3.effectId);
|
||||
REQUIRE(true==foregroundEffRef.expired());
|
||||
REQUIRE(true==foregroundEffRef3.foregroundEffect);
|
||||
REQUIRE(false==foregroundEffRef3.expired());
|
||||
Game::Update(0.5f);
|
||||
REQUIRE(size_t(0)==EffectManager::GetForegroundEffectCount());
|
||||
REQUIRE(size_t(0)==EffectManager::GetBackgroundEffectCount());
|
||||
REQUIRE(true==foregroundEffRef3.expired());
|
||||
REQUIRE(true==foregroundEffRef.expired());
|
||||
REQUIRE(true==backgroundEffRef.expired());
|
||||
REQUIRE(true==foregroundEffRef2.expired());
|
||||
}
|
||||
TEST(EffectTests,"GettingExpiredEffectRefObjectFails"){
|
||||
Effect newEff{vf2d{},0.5f,"pixel.png",false,0.f};
|
||||
auto backgroundEffRef{game->AddEffect(newEff)};
|
||||
Game::Update(0.5f);
|
||||
REQUIRE_THROWS_AS(backgroundEffRef.get(),std::runtime_error);
|
||||
}
|
||||
TEST(EffectTests,"AddAndRemovalOfEffectsInMiddleOfArray"){
|
||||
auto eff1{game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f})};
|
||||
auto eff2{game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f})};
|
||||
auto eff3{game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f})};
|
||||
auto eff4{game->AddEffect(Effect{vf2d{},0.25f,"pixel.png",false,0.f})};
|
||||
auto eff5{game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f})};
|
||||
Game::Update(0.25f);
|
||||
auto eff6{game->AddEffect(Effect{vf2d{},0.25f,"pixel.png",false,0.f})};
|
||||
auto eff7{game->AddEffect(Effect{vf2d{},0.25f,"pixel.png",false,0.f})};
|
||||
REQUIRE(eff6.slotId==eff4.slotId);
|
||||
REQUIRE(eff6.effectId!=eff4.effectId);
|
||||
REQUIRE(5==eff7.slotId);
|
||||
}
|
||||
TEST(EffectTests,"AddNewEffectWhenArrayIsFull"){
|
||||
for(int i:std::ranges::iota_view(0,EFFECT_LIMIT)){
|
||||
game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f});
|
||||
game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f},true);
|
||||
}
|
||||
EFF(*EffectManager::GetForegroundEffects()[50].effect).aliveTime=200.f;
|
||||
int oldEffectId{EffectManager::GetForegroundEffects()[50].effectId};
|
||||
EffectRef replacedEff{game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f})};
|
||||
REQUIRE(oldEffectId<replacedEff.effectId);
|
||||
}
|
||||
TEST(EffectTests,"CheckForGapInExpiryTimes"){
|
||||
for(int i:std::ranges::iota_view(0,EFFECT_LIMIT)){
|
||||
if(i==40){
|
||||
game->AddEffect(Effect{vf2d{},0.1f,"pixel.png",false,0.f});
|
||||
game->AddEffect(Effect{vf2d{},0.1f,"pixel.png",false,0.f},true);
|
||||
}else{
|
||||
game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f});
|
||||
game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f},true);
|
||||
}
|
||||
}
|
||||
Game::Update(0.1f);
|
||||
REQUIRE(false==bool(EffectManager::GetForegroundEffects()[40].effect));
|
||||
REQUIRE(false==bool(EffectManager::GetBackgroundEffects()[40].effect));
|
||||
EffectRef foregroundEff{game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f})};
|
||||
EffectRef backgroundEff{game->AddEffect(Effect{vf2d{},0.5f,"pixel.png",false,0.f},true)};
|
||||
REQUIRE(40==foregroundEff.slotId);
|
||||
REQUIRE(40==backgroundEff.slotId);
|
||||
}
|
||||
|
||||
1314
Adventures in Lestoria/tests/EnchantTests.cpp
Normal file
1314
Adventures in Lestoria/tests/EnchantTests.cpp
Normal file
File diff suppressed because it is too large
Load Diff
190
Adventures in Lestoria/tests/EngineTests.cpp
Normal file
190
Adventures in Lestoria/tests/EngineTests.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "Tutorial.h"
|
||||
#include <random>
|
||||
#include "ItemDrop.h"
|
||||
#include"SoundEffect.h"
|
||||
#include"catch.h"
|
||||
|
||||
|
||||
INCLUDE_GFX
|
||||
INCLUDE_ITEM_DATA
|
||||
INCLUDE_DAMAGENUMBER_LIST
|
||||
INCLUDE_INITIALIZEGAMECONFIGURATIONS
|
||||
|
||||
extern std::mt19937 rng;
|
||||
|
||||
class EngineTests{
|
||||
public:
|
||||
std::unique_ptr<AiL>testGame;
|
||||
InputGroup testKeyboardInput;
|
||||
Player*player;
|
||||
HWButton*testKey;
|
||||
EngineTests(){
|
||||
InitializeGameConfigurations();
|
||||
rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run.
|
||||
testGame.reset(new AiL(true));
|
||||
ItemAttribute::Initialize();
|
||||
ItemInfo::InitializeItems();
|
||||
testGame->InitializeGraphics();
|
||||
testGame->InitializeClasses();
|
||||
sig::Animation::InitializeAnimations();
|
||||
testGame->InitializeDefaultKeybinds();
|
||||
testGame->InitializePlayer();
|
||||
sig::Animation::SetupPlayerAnimations();
|
||||
Menu::InitializeMenus();
|
||||
Tutorial::Initialize();
|
||||
Stats::InitializeDamageReductionTable();
|
||||
SoundEffect::Initialize();
|
||||
|
||||
GameState::Initialize();
|
||||
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
|
||||
|
||||
#pragma region Setup a fake test map and test monster
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
ItemDrop::ClearDrops();
|
||||
MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
MONSTER_DATA["TestName"]=testMonsterData;
|
||||
#pragma endregion
|
||||
testGame->ResetLevelStates();
|
||||
|
||||
player=testGame->GetPlayer();
|
||||
//Setup key "0" as a test input
|
||||
testKeyboardInput.AddKeybind(Input{InputType::KEY,0});
|
||||
testKey=testGame->GetKeyboardState(0);
|
||||
testGame->olc_UpdateKeyFocus(true); //Force the game to be "focused" for tests. Required if we want keyboard inputs to work.
|
||||
Menu::themes.SetInitialized();
|
||||
GFX.SetInitialized();
|
||||
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
~EngineTests(){
|
||||
testGame->EndGame();
|
||||
testGame->OnUserUpdate(0.f);
|
||||
testGame.reset();
|
||||
}
|
||||
};
|
||||
TEST(EngineTests,"StripColorTest"){
|
||||
std::string noColCode{"Hello World!"};
|
||||
REQUIRE("Hello World!"s==testGame->stripCol(noColCode));
|
||||
std::string leadingColCode{"#FFFFFFHello World!"};
|
||||
REQUIRE("Hello World!"s==testGame->stripCol(leadingColCode));
|
||||
std::string extraColCodes{"#FFFFFFHello #00FF00World!"};
|
||||
REQUIRE("Hello World!"s==testGame->stripCol(extraColCodes));
|
||||
std::u32string u32noColCode{noColCode.begin(),noColCode.end()};
|
||||
std::u32string u32noColCodeResult{testGame->stripCol(u32noColCode)};
|
||||
REQUIRE("Hello World!"s==std::string{u32noColCodeResult.begin(),u32noColCodeResult.end()});
|
||||
std::u32string u32leadingColCode{noColCode.begin(),noColCode.end()};
|
||||
std::u32string u32leadingColCodeResult{testGame->stripCol(u32leadingColCode)};
|
||||
REQUIRE("Hello World!"s==std::string{u32leadingColCodeResult.begin(),u32leadingColCodeResult.end()});
|
||||
std::u32string u32extraColCodes{extraColCodes.begin(),extraColCodes.end()};
|
||||
std::u32string u32extraColCodesResult{testGame->stripCol(u32extraColCodes)};
|
||||
REQUIRE("Hello World!"s==std::string{u32extraColCodesResult.begin(),u32extraColCodesResult.end()});
|
||||
}
|
||||
TEST(EngineTests,"StripLeadingColorTest"){
|
||||
std::string noColCode{"Hello World!"};
|
||||
REQUIRE("Hello World!"s==testGame->stripLeadingCol(noColCode));
|
||||
std::string leadingColCode{"#FFFFFFHello World!"};
|
||||
REQUIRE("Hello World!"s==testGame->stripLeadingCol(leadingColCode));
|
||||
std::string extraColCodes{"#FFFFFFHello #00FF00World!"};
|
||||
REQUIRE("Hello #00FF00World!"s==testGame->stripLeadingCol(extraColCodes));
|
||||
std::u32string u32noColCode{noColCode.begin(),noColCode.end()};
|
||||
std::u32string u32noColCodeResult{testGame->stripLeadingCol(u32noColCode)};
|
||||
REQUIRE("Hello World!"s==std::string{u32noColCodeResult.begin(),u32noColCodeResult.end()});
|
||||
std::u32string u32leadingColCode{noColCode.begin(),noColCode.end()};
|
||||
std::u32string u32leadingColCodeResult{testGame->stripLeadingCol(u32leadingColCode)};
|
||||
REQUIRE("Hello World!"s==std::string{u32leadingColCodeResult.begin(),u32leadingColCodeResult.end()});
|
||||
std::u32string u32extraColCodes{extraColCodes.begin(),extraColCodes.end()};
|
||||
std::u32string u32extraColCodesResult{testGame->stripLeadingCol(u32extraColCodes)};
|
||||
REQUIRE("Hello #00FF00World!"s==std::string{u32extraColCodesResult.begin(),u32extraColCodesResult.end()});
|
||||
}
|
||||
TEST(EngineTests,"GetFinalRenderColorTest"){
|
||||
REQUIRE(WHITE.n==testGame->GetFinalRenderColor(WHITE,"Hello World!").n);
|
||||
REQUIRE(BLUE.n==testGame->GetFinalRenderColor(WHITE,"#0000FFHello World!").n);
|
||||
REQUIRE(BLUE.n==testGame->GetFinalRenderColor(WHITE,"#0000FFHello #00FF00World!").n);
|
||||
REQUIRE(WHITE.n==testGame->GetFinalRenderColor(WHITE,"Hello #00FF00World!").n);
|
||||
std::string testStr{"Hello World!"};
|
||||
std::u32string u32testStr{testStr.begin(),testStr.end()};
|
||||
REQUIRE(WHITE.n==testGame->GetFinalRenderColor(WHITE,testStr).n);
|
||||
std::string colorCodeStr{"#0000FFHello World!"};
|
||||
std::u32string u32colorCodeStr{colorCodeStr.begin(),colorCodeStr.end()};
|
||||
REQUIRE(BLUE.n==testGame->GetFinalRenderColor(WHITE,colorCodeStr).n);
|
||||
std::string extraColorCodeStr{"#0000FFHello #00FF00World!"};
|
||||
std::u32string u32extraColorCodeStr{extraColorCodeStr.begin(),extraColorCodeStr.end()};
|
||||
REQUIRE(BLUE.n==testGame->GetFinalRenderColor(WHITE,extraColorCodeStr).n);
|
||||
std::string middleColorCodeStr{"Hello #00FF00World!"};
|
||||
std::u32string u32middleColorCodeStr{middleColorCodeStr.begin(),middleColorCodeStr.end()};
|
||||
REQUIRE(WHITE.n==testGame->GetFinalRenderColor(WHITE,middleColorCodeStr).n);
|
||||
}
|
||||
TEST(EngineTests,"UtilMapRangeTest"){
|
||||
REQUIRE(0.f==util::map_range<float>(0.f,0,100,0,100));
|
||||
REQUIRE(100.f==util::map_range<float>(100.f,0,100,0,100));
|
||||
REQUIRE(50.f==util::map_range<float>(50.f,0,100,0,100));
|
||||
|
||||
REQUIRE(0.f==util::map_range<float>(0.f,0,50,0,100));
|
||||
REQUIRE(200.f==util::map_range<float>(100.f,0,50,0,100));
|
||||
REQUIRE(100.f==util::map_range<float>(50.f,0,50,0,100));
|
||||
|
||||
REQUIRE(100.f==util::map_range<float>(0.f,0,100,100,200));
|
||||
REQUIRE(200.f==util::map_range<float>(100.f,0,100,100,200));
|
||||
REQUIRE(150.f==util::map_range<float>(50.f,0,100,100,200));
|
||||
|
||||
REQUIRE(0.f==util::map_range<float>(0.f,50,100,100,200));
|
||||
REQUIRE(200.f==util::map_range<float>(100.f,50,100,100,200));
|
||||
REQUIRE(100.f==util::map_range<float>(50.f,50,100,100,200));
|
||||
}
|
||||
|
||||
TEST(EngineTests,"ClassUtilTest"){
|
||||
REQUIRE(int(Class::WARRIOR)==int(classutils::StringToClass("Warrior")));
|
||||
REQUIRE(int(Class::WIZARD)==int(classutils::StringToClass("Wizard")));
|
||||
REQUIRE(int(Class::RANGER)==int(classutils::StringToClass("Ranger")));
|
||||
REQUIRE(int(Class::THIEF)==int(classutils::StringToClass("Thief")));
|
||||
REQUIRE(int(Class::WITCH)==int(classutils::StringToClass("Witch")));
|
||||
REQUIRE(int(Class::TRAPPER)==int(classutils::StringToClass("Trapper")));
|
||||
|
||||
REQUIRE("Warrior"==classutils::ClassToString(Class::WARRIOR));
|
||||
REQUIRE("Wizard"==classutils::ClassToString(Class::WIZARD));
|
||||
REQUIRE("Ranger"==classutils::ClassToString(Class::RANGER));
|
||||
REQUIRE("Thief"==classutils::ClassToString(Class::THIEF));
|
||||
REQUIRE("Witch"==classutils::ClassToString(Class::WITCH));
|
||||
REQUIRE("Trapper"==classutils::ClassToString(Class::TRAPPER));
|
||||
}
|
||||
127
Adventures in Lestoria/tests/FileTests.cpp
Normal file
127
Adventures in Lestoria/tests/FileTests.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "config.h"
|
||||
#include "ItemDrop.h"
|
||||
#include "Tutorial.h"
|
||||
#include "DamageNumber.h"
|
||||
#include "GameHelper.h"
|
||||
#include "SaveFile.h"
|
||||
#include"SoundEffect.h"
|
||||
#include <ranges>
|
||||
|
||||
using namespace olc::utils;
|
||||
|
||||
INCLUDE_MONSTER_DATA
|
||||
INCLUDE_game
|
||||
INCLUDE_GFX
|
||||
INCLUDE_DAMAGENUMBER_LIST
|
||||
INCLUDE_MONSTER_LIST
|
||||
INCLUDE_INITIALIZEGAMECONFIGURATIONS
|
||||
|
||||
class FileTests{
|
||||
public:
|
||||
std::unique_ptr<AiL>testGame;
|
||||
FileTests(){
|
||||
SetupTest();
|
||||
SetupMockMap();
|
||||
}
|
||||
~FileTests(){
|
||||
testGame->EndGame();
|
||||
testGame->OnUserUpdate(0.f);
|
||||
testGame.reset();
|
||||
}
|
||||
#pragma region Setup Functions
|
||||
void SetupTest(){
|
||||
InitializeGameConfigurations();
|
||||
testGame.reset(new AiL(true));
|
||||
ItemAttribute::Initialize();
|
||||
ItemInfo::InitializeItems();
|
||||
testGame->InitializeGraphics();
|
||||
testGame->InitializeClasses();
|
||||
sig::Animation::InitializeAnimations();
|
||||
testGame->InitializeDefaultKeybinds();
|
||||
testGame->InitializePlayer();
|
||||
sig::Animation::SetupPlayerAnimations();
|
||||
Menu::InitializeMenus();
|
||||
Tutorial::Initialize();
|
||||
Stats::InitializeDamageReductionTable();
|
||||
SoundEffect::Initialize();
|
||||
|
||||
GameState::Initialize();
|
||||
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
|
||||
testGame->ResetLevelStates();
|
||||
|
||||
#pragma region Setup a fake test map
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
Game::_SetCurrentLevel("CAMPAIGN_1_1");
|
||||
ItemDrop::ClearDrops();
|
||||
#pragma endregion
|
||||
|
||||
MonsterData testMonsterData{"TestName","Test Monster",30,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
MONSTER_DATA["TestName"]=testMonsterData;
|
||||
|
||||
Menu::themes.SetInitialized();
|
||||
GFX.SetInitialized();
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
void SetupMockMap(){
|
||||
game->MAP_DATA.at("CAMPAIGN_1_1")=Map{};
|
||||
ItemDrop::ClearDrops();
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
};
|
||||
|
||||
TEST(FileTests,"ImageLoadsProperRegardlessOfCaseSensitivity"){
|
||||
Sprite testSpr;
|
||||
REQUIRE(int(olc::rcode::OK)==int(testSpr.LoadFromFile("assets/title_transparent.png")));
|
||||
REQUIRE_THROWS_AS(testSpr.LoadFromFile("assets/title_transparentfdjakl.png"),std::runtime_error);
|
||||
REQUIRE(int(olc::rcode::OK)==int(testSpr.LoadFromFile("assets/title_transparent.png")));
|
||||
REQUIRE(int(olc::rcode::OK)==int(testSpr.LoadFromFile("assets/TITle_transparent.PNg")));
|
||||
}
|
||||
TEST(FileTests,"DataFileLoadsProperRegardlessOfCaseSensitivity"){
|
||||
datafile data;
|
||||
REQUIRE(datafile::Read(data,"assets/config/credits.txt"));
|
||||
data.Reset();
|
||||
REQUIRE_THROWS_AS(datafile::Read(data,"assets/config/creditsfdsfdsafd.txt"),std::runtime_error);
|
||||
data.Reset();
|
||||
REQUIRE(datafile::Read(data,"assets/config/credITS.tXt"));
|
||||
}
|
||||
10
Adventures in Lestoria/tests/GeometryTests.cpp
Normal file
10
Adventures in Lestoria/tests/GeometryTests.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include "catch.h"
|
||||
#include"olcUTIL_Geometry2D.h"
|
||||
|
||||
class GeometryTests{
|
||||
public:
|
||||
};
|
||||
|
||||
TEST(GeometryTests,"Circle overlap test") {
|
||||
REQUIRE( geom2d::overlaps(geom2d::circle<float>{vf2d{},10},vf2d{5,5}) );
|
||||
}
|
||||
465
Adventures in Lestoria/tests/ItemTests.cpp
Normal file
465
Adventures in Lestoria/tests/ItemTests.cpp
Normal file
@ -0,0 +1,465 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "Tutorial.h"
|
||||
#include <random>
|
||||
#include <format>
|
||||
#include "ItemDrop.h"
|
||||
#include <ranges>
|
||||
#include "GameHelper.h"
|
||||
#include"RowInventoryScrollableWindowComponent.h"
|
||||
#include"SaveFile.h"
|
||||
#include"SoundEffect.h"
|
||||
|
||||
using namespace olc::utils;
|
||||
|
||||
INCLUDE_GFX
|
||||
INCLUDE_ITEM_DATA
|
||||
INCLUDE_INITIALIZEGAMECONFIGURATIONS
|
||||
|
||||
extern std::mt19937 rng;
|
||||
|
||||
class ItemTests{
|
||||
public:
|
||||
std::unique_ptr<AiL>testGame;
|
||||
InputGroup testKeyboardInput;
|
||||
Player*player;
|
||||
HWButton*testKey;
|
||||
ItemTests(){
|
||||
InitializeGameConfigurations();
|
||||
rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run.
|
||||
testGame.reset(new AiL(true));
|
||||
ItemAttribute::Initialize();
|
||||
ItemInfo::InitializeItems();
|
||||
testGame->InitializeGraphics();
|
||||
testGame->InitializeClasses();
|
||||
sig::Animation::InitializeAnimations();
|
||||
Monster::InitializeStrategies();
|
||||
MonsterData::InitializeMonsterData();
|
||||
sig::Animation::InitializeAnimations();
|
||||
testGame->InitializeDefaultKeybinds();
|
||||
testGame->InitializePlayer();
|
||||
sig::Animation::SetupPlayerAnimations();
|
||||
Menu::InitializeMenus();
|
||||
Tutorial::Initialize();
|
||||
Stats::InitializeDamageReductionTable();
|
||||
SoundEffect::Initialize();
|
||||
GameState::Initialize();
|
||||
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
|
||||
|
||||
testGame->ResetLevelStates();
|
||||
#pragma region Setup a fake test map and test monster
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
game->MAP_DATA["HUB_TYPE_TEST_MAP"];
|
||||
game->MAP_DATA["WORLD_TYPE_TEST_MAP"];
|
||||
ItemDrop::ClearDrops();
|
||||
MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
MONSTER_DATA["TestName"]=testMonsterData;
|
||||
#pragma endregion
|
||||
|
||||
player=testGame->GetPlayer();
|
||||
//Setup key "0" as a test input
|
||||
testKeyboardInput.AddKeybind(Input{InputType::KEY,0});
|
||||
testKey=testGame->GetKeyboardState(0);
|
||||
testGame->olc_UpdateKeyFocus(true); //Force the game to be "focused" for tests. Required if we want keyboard inputs to work.
|
||||
Menu::themes.SetInitialized();
|
||||
GFX.SetInitialized();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
MapTag dungeonMapData{};
|
||||
game->MAP_DATA["HUB_TYPE_TEST_MAP"].mapType=Map::MapType::HUB;
|
||||
game->MAP_DATA["WORLD_TYPE_TEST_MAP"].mapType=Map::MapType::WORLD_MAP;
|
||||
}
|
||||
~ItemTests(){
|
||||
testGame->EndGame();
|
||||
testGame->OnUserUpdate(0.f);
|
||||
testGame.reset();
|
||||
}
|
||||
};
|
||||
TEST(ItemTests,"ItemGiveTest"){
|
||||
Inventory::AddItem("Health Potion"s,3);
|
||||
REQUIRE(3U==Inventory::GetItemCount("Health Potion"s));
|
||||
}
|
||||
TEST(ItemTests,"ItemAddAndRemoveAffectsStageLootTest"){
|
||||
REQUIRE(size_t(0)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(0)==Inventory::get("Monster Loot").size());
|
||||
Game::LoadLevelWithTMX("CAMPAIGN_1_1",testGame.get());
|
||||
REQUIRE(size_t(0)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(0)==Inventory::get("Monster Loot").size());
|
||||
Inventory::AddItem("Health Potion"s,3);
|
||||
REQUIRE(size_t(1)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(0)==Inventory::get("Monster Loot").size());
|
||||
Inventory::AddItem("Health Potion"s,3,true);
|
||||
REQUIRE(size_t(1)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(1)==Inventory::get("Monster Loot").size());
|
||||
Game::LoadLevelWithTMX("BOSS_1",testGame.get());
|
||||
REQUIRE(size_t(0)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(0)==Inventory::get("Monster Loot").size());
|
||||
Inventory::AddItem("Health Potion"s,3);
|
||||
REQUIRE(size_t(1)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(0)==Inventory::get("Monster Loot").size());
|
||||
Inventory::AddItem("Health Potion"s,3,true);
|
||||
REQUIRE(size_t(1)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(1)==Inventory::get("Monster Loot").size());
|
||||
Game::LoadFakeLevel("HUB_TYPE_TEST_MAP",testGame.get());
|
||||
REQUIRE(size_t(0)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(0)==Inventory::get("Monster Loot").size());
|
||||
Inventory::AddItem("Health Potion"s,3);
|
||||
REQUIRE(size_t(0)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(0)==Inventory::get("Monster Loot").size());
|
||||
Inventory::AddItem("Health Potion"s,3,true);
|
||||
REQUIRE(size_t(0)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(0)==Inventory::get("Monster Loot").size());
|
||||
Game::LoadFakeLevel("WORLD_TYPE_TEST_MAP",testGame.get());
|
||||
REQUIRE(size_t(0)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(0)==Inventory::get("Monster Loot").size());
|
||||
Inventory::AddItem("Health Potion"s,3);
|
||||
REQUIRE(size_t(0)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(0)==Inventory::get("Monster Loot").size());
|
||||
Inventory::AddItem("Health Potion"s,3,true);
|
||||
REQUIRE(size_t(0)==Inventory::get("Stage Loot").size());
|
||||
REQUIRE(size_t(0)==Inventory::get("Monster Loot").size());
|
||||
}
|
||||
TEST(ItemTests,"ItemRemoveTest"){
|
||||
Inventory::AddItem("Health Potion"s,3);
|
||||
for(std::weak_ptr<Item>&item:Inventory::GetItem("Health Potion"s))Inventory::RemoveItem(item,3);
|
||||
REQUIRE(0U==Inventory::GetItemCount("Health Potion"s));
|
||||
}
|
||||
TEST(ItemTests,"ItemQuantityStackTest"){
|
||||
Inventory::AddItem("Health Potion"s,3);
|
||||
Inventory::AddItem("Health Potion"s,3);
|
||||
REQUIRE(6U==Inventory::GetItemCount("Health Potion"s));
|
||||
}
|
||||
TEST(ItemTests,"EquipmentNoStackTest"){
|
||||
Inventory::AddItem("Ring of the Slime King"s);
|
||||
Inventory::AddItem("Ring of the Slime King"s);
|
||||
Inventory::AddItem("Ring of the Slime King"s);
|
||||
int itemCounter{};
|
||||
for(std::weak_ptr<Item>&item:Inventory::GetItem("Ring of the Slime King"s))itemCounter++;
|
||||
REQUIRE(3==itemCounter);
|
||||
}
|
||||
TEST(ItemTests,"UsingBlankLoadoutItemDoesNothing"){
|
||||
REQUIRE(!game->UseLoadoutItem(0));
|
||||
REQUIRE(!game->UseLoadoutItem(1));
|
||||
REQUIRE(!game->UseLoadoutItem(2));
|
||||
}
|
||||
TEST(ItemTests,"UsingLoadoutItemOfQuantityZeroDoesNothing"){
|
||||
REQUIRE_THROWS_AS(game->SetLoadoutItem(0,"Minor Health Potion"),std::exception);
|
||||
}
|
||||
TEST(ItemTests,"UsingLoadoutItemConsumesIt"){
|
||||
player->Hurt(1,player->OnUpperLevel(),player->GetZ());
|
||||
Inventory::AddItem("Minor Health Potion"s,5U);
|
||||
game->SetLoadoutItem(0,"Minor Health Potion");
|
||||
testKey->bHeld=true; //Simulate key being pressed.
|
||||
player->CheckAndPerformAbility(player->GetItem1(),testKeyboardInput);
|
||||
REQUIRE(1==Inventory::loadoutItemsUsed[0].second);
|
||||
REQUIRE(4U==Inventory::GetItemCount("Minor Health Potion"s));
|
||||
REQUIRE(player->GetItem1().GetCooldownTime()==player->GetItem1().cooldown);
|
||||
}
|
||||
TEST(ItemTests,"ItemScriptBuffTest"){
|
||||
player->Hurt(1,player->OnUpperLevel(),player->GetZ());
|
||||
Inventory::AddItem("Stat Up Everything Potion"s,5U);
|
||||
game->SetLoadoutItem(0,"Stat Up Everything Potion");
|
||||
testKey->bHeld=true; //Simulate key being pressed.
|
||||
REQUIRE_THROWS_AS(player->CheckAndPerformAbility(player->GetItem1(),testKeyboardInput),std::exception);
|
||||
}
|
||||
TEST(ItemTests,"FlatRestoreScriptTest"){
|
||||
player->Hurt(75,player->OnUpperLevel(),player->GetZ());
|
||||
player->ConsumeMana(76);
|
||||
Inventory::AddItem("Flat Recovery Potion"s,5U);
|
||||
game->SetLoadoutItem(0,"Flat Recovery Potion");
|
||||
testKey->bHeld=true; //Simulate key being pressed.
|
||||
player->CheckAndPerformAbility(player->GetItem1(),testKeyboardInput);
|
||||
game->OnUserUpdate(0.f); //Wait an extra tick for the buff to begin going down.
|
||||
game->SetElapsedTime(0.05f);
|
||||
game->OnUserUpdate(0.05f);//Wait some time as the item applies a buff that heals us. We're also going to gain one mana during this tick.
|
||||
REQUIRE(75==player->GetHealth());
|
||||
REQUIRE(75==player->GetMana());
|
||||
}
|
||||
TEST(ItemTests,"PctRestoreScriptTest"){
|
||||
player->Hurt(75,player->OnUpperLevel(),player->GetZ());
|
||||
player->ConsumeMana(76);
|
||||
Inventory::AddItem("Pct Recovery Potion"s,5U);
|
||||
game->SetLoadoutItem(1,"Pct Recovery Potion");
|
||||
testKey->bHeld=true; //Simulate key being pressed.
|
||||
player->CheckAndPerformAbility(player->GetItem2(),testKeyboardInput);
|
||||
game->OnUserUpdate(0.f); //Wait an extra tick for the buff to begin going down.
|
||||
game->SetElapsedTime(0.05f);
|
||||
game->OnUserUpdate(0.05f);//Wait some time as the item applies a buff that heals us.
|
||||
REQUIRE(75==player->GetHealth());
|
||||
REQUIRE(75==player->GetMana());
|
||||
}
|
||||
TEST(ItemTests,"HealOverTimeTest"){
|
||||
player->Hurt(75,player->OnUpperLevel(),player->GetZ());
|
||||
Inventory::AddItem("Bandages"s,5U);
|
||||
game->SetLoadoutItem(2,"Bandages");
|
||||
testKey->bHeld=true; //Simulate key being pressed.
|
||||
player->CheckAndPerformAbility(player->GetItem3(),testKeyboardInput);
|
||||
game->OnUserUpdate(0.f); //Wait an extra tick for the buff to begin going down.
|
||||
game->SetElapsedTime(0.05f);
|
||||
game->OnUserUpdate(0.05f);//Wait some time as the item applies a buff that heals us.
|
||||
REQUIRE(30==player->GetHealth());
|
||||
game->SetElapsedTime(1.f);
|
||||
game->OnUserUpdate(1.f);
|
||||
for(int seconds{1};seconds<=6;seconds++){
|
||||
REQUIRE(30+seconds*5==player->GetHealth());
|
||||
game->OnUserUpdate(1.f);
|
||||
}
|
||||
REQUIRE(60==player->GetHealth());
|
||||
}
|
||||
TEST(ItemTests,"DisassembleAccessoryTest"){
|
||||
Inventory::AddItem("Ring of the Slime King"s);
|
||||
std::weak_ptr<Item>disassembleRingTest{Inventory::AddItem("Ring of the Slime King"s)};
|
||||
Inventory::AddItem("Ring of the Slime King"s);
|
||||
|
||||
Inventory::Disassemble(disassembleRingTest);
|
||||
REQUIRE(2U==Inventory::GetItemCount("Ring of the Slime King"s));
|
||||
REQUIRE(disassembleRingTest.expired());
|
||||
REQUIRE(1U==Inventory::GetItemCount(ITEM_DATA["Ring of the Slime King"].FragmentName()));
|
||||
}
|
||||
TEST(ItemTests,"DisassembleNonAccessoryTest"){
|
||||
Inventory::AddItem("Ring of the Slime King"s);
|
||||
try{
|
||||
Inventory::Disassemble(Inventory::AddItem("Test Armor"s));
|
||||
FAIL("Disassembling Test Armor succeeded! This should NOT be allowed!");
|
||||
}catch(std::runtime_error&e){}
|
||||
try{
|
||||
Inventory::Disassemble(Inventory::AddItem("Green Slime Remains"s));
|
||||
FAIL("Disassembling Green Slime Remains succeeded! This should NOT be allowed!");
|
||||
}catch(std::runtime_error&e){}
|
||||
try{
|
||||
Inventory::Disassemble(Inventory::AddItem("Health Potion"s));
|
||||
FAIL("Disassembling a Health Potion succeeded! This should NOT be allowed!");
|
||||
}catch(std::runtime_error&e){}
|
||||
}
|
||||
TEST(ItemTests,"RefiningTest"){
|
||||
std::weak_ptr<Item>slimeKingRing{Inventory::AddItem("Ring of the Slime King"s)};
|
||||
REQUIRE(!slimeKingRing.lock()->CanBeRefined());
|
||||
std::weak_ptr<Item>testArmor{Inventory::AddItem("Test Armor"s)};
|
||||
REQUIRE(!testArmor.lock()->CanBeRefined());
|
||||
Inventory::AddItem(slimeKingRing.lock()->FragmentName(),50U);
|
||||
Inventory::EquipItem(slimeKingRing,EquipSlot::RING1);
|
||||
REQUIRE(slimeKingRing.lock()->CanBeRefined());
|
||||
player->SetMoney(0);
|
||||
REQUIRE(!slimeKingRing.lock()->CanBeRefined());
|
||||
player->SetMoney(10000);
|
||||
while(slimeKingRing.lock()->CanBeRefined()){
|
||||
RefineResult result{slimeKingRing.lock()->Refine()};
|
||||
LOG(std::format("Enhanced {} by {}",result.first.Name(),result.second));
|
||||
}
|
||||
for(const auto&[attr,val]:slimeKingRing.lock()->RandomStats()){
|
||||
REQUIRE(ITEM_DATA[slimeKingRing.lock()->ActualName()].GetMaxStats().A_Read(attr)==val);
|
||||
}
|
||||
/*Ring of the Slime King has the following refining stats:
|
||||
* StatValues = Health,Mana,Move Spd %
|
||||
MinStats = 5,1,1
|
||||
MaxStats = 20,4,3
|
||||
*
|
||||
Therefore, after this process is done the player should have 20 more health, 4 more mana, and 3% more move speed than normal.
|
||||
*/
|
||||
//These checks make sure that the refining call actually modifies already equipped items!
|
||||
REQUIRE(120==player->GetMaxHealth());
|
||||
REQUIRE(104==player->GetMaxMana());
|
||||
REQUIRE(1.03f==player->GetMoveSpdMult());
|
||||
}
|
||||
TEST(ItemTests,"EnchantTestCheck"){
|
||||
std::weak_ptr<Item>slimeKingRing{Inventory::AddItem("Ring of the Slime King"s)};
|
||||
REQUIRE(!slimeKingRing.lock()->HasEnchant());
|
||||
bool obtainedDuplicate{false};
|
||||
for(int i:std::ranges::iota_view(0,1000)){
|
||||
std::optional<ItemEnchant>previousEnchant{slimeKingRing.lock()->GetEnchant()};
|
||||
std::string previousEnchantName{};
|
||||
if(slimeKingRing.lock()->HasEnchant())previousEnchantName=slimeKingRing.lock()->GetEnchant().value().Name();
|
||||
slimeKingRing.lock()->_EnchantItem(ItemEnchant::RollRandomEnchant(previousEnchant));
|
||||
REQUIRE(slimeKingRing.lock()->HasEnchant());
|
||||
if(previousEnchantName==slimeKingRing.lock()->GetEnchant().value().Name()){
|
||||
bool improvementExists{false};
|
||||
std::string statDowngrades{};
|
||||
if(previousEnchant.value().HasAttributes()){
|
||||
for(const auto&[attr,val]:previousEnchant.value()){
|
||||
if(slimeKingRing.lock()->GetEnchant().value().GetAttribute(attr.ActualName())>val){
|
||||
improvementExists=true;
|
||||
break;
|
||||
}else statDowngrades+=std::format("{} - Previous:{}, New:{}\n",attr.Name(),val,slimeKingRing.lock()->GetEnchant().value().GetAttribute(attr.ActualName()));
|
||||
}
|
||||
}else improvementExists=true;
|
||||
REQUIRE(improvementExists);
|
||||
obtainedDuplicate=true;
|
||||
}
|
||||
if(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().has_value())REQUIRE(int(player->GetClass())==int(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().value())); //Validate enchant is only for this class if it's a class-based ability.
|
||||
}
|
||||
Game::ResetPlayerAndChangeClass(WIZARD,player,&*testGame);
|
||||
for(int i:std::ranges::iota_view(0,1000)){
|
||||
std::optional<ItemEnchant> previousEnchant{slimeKingRing.lock()->GetEnchant()};
|
||||
std::string previousEnchantName{};
|
||||
if(slimeKingRing.lock()->HasEnchant())previousEnchantName=slimeKingRing.lock()->GetEnchant().value().Name();
|
||||
slimeKingRing.lock()->_EnchantItem(ItemEnchant::RollRandomEnchant(previousEnchant));
|
||||
REQUIRE(slimeKingRing.lock()->HasEnchant());
|
||||
if(previousEnchantName==slimeKingRing.lock()->GetEnchant().value().Name()){
|
||||
bool improvementExists{false};
|
||||
std::string statDowngrades{};
|
||||
if(previousEnchant.value().HasAttributes()){
|
||||
for(const auto&[attr,val]:previousEnchant.value()){
|
||||
if(slimeKingRing.lock()->GetEnchant().value().GetAttribute(attr.ActualName())>val){
|
||||
improvementExists=true;
|
||||
break;
|
||||
}else statDowngrades+=std::format("{} - Previous:{}, New:{}\n",attr.Name(),val,slimeKingRing.lock()->GetEnchant().value().GetAttribute(attr.ActualName()));
|
||||
}
|
||||
}else improvementExists=true;
|
||||
REQUIRE(improvementExists);
|
||||
obtainedDuplicate=true;
|
||||
}
|
||||
if(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().has_value())REQUIRE(int(player->GetClass())==int(ItemEnchantInfo::ENCHANT_LIST.at(slimeKingRing.lock()->GetEnchant().value().Name()).GetClass().value())); //Validate enchant is only for this class if it's a class-based ability.
|
||||
}
|
||||
REQUIRE(obtainedDuplicate);
|
||||
}
|
||||
TEST(ItemTests,"AccessoryAntiCompatibilityCheck"){
|
||||
std::weak_ptr<Item>extraRing{Inventory::AddItem("Ring of the Slime King"s)};
|
||||
std::weak_ptr<Item>extraRing2{Inventory::AddItem("Ring of the Slime King"s)};
|
||||
|
||||
Inventory::EquipItem(extraRing,EquipSlot::RING2);
|
||||
REQUIRE(Item::SelectedEquipIsDifferent(extraRing2,EquipSlot::RING1));
|
||||
REQUIRE(!Item::SelectedEquipIsDifferent(extraRing,EquipSlot::RING1));
|
||||
Inventory::UnequipItem(EquipSlot::RING2);
|
||||
REQUIRE(Item::SelectedEquipIsDifferent(extraRing,EquipSlot::RING1));
|
||||
}
|
||||
TEST(ItemTests,"AccessoryRandomEnchantTest"){
|
||||
std::weak_ptr<Item>extraRing{Inventory::AddItem("Ring of the Slime King"s)};
|
||||
std::unordered_map<ItemEnchantInfo::ItemEnchantCategory,uint32_t>enchantCounts;
|
||||
for(int i:std::ranges::iota_view(0,1000)){
|
||||
Inventory::AddItem(extraRing.lock()->FragmentName(),"Fragment Enchant Cost"_i[0]);
|
||||
player->AddMoney("Fragment Enchant Cost"_i[1]);
|
||||
const ItemEnchant&resultEnchant{extraRing.lock()->ApplyRandomEnchant()};
|
||||
if(resultEnchant.GetClass().has_value())REQUIRE(int(resultEnchant.GetClass().value())==int(player->GetClass()));
|
||||
enchantCounts[resultEnchant.Category()]++;
|
||||
REQUIRE(extraRing.lock()->GetEnchant().has_value());
|
||||
REQUIRE(resultEnchant.Name()==extraRing.lock()->GetEnchant().value().Name());
|
||||
REQUIRE(!player->HasEnchant(resultEnchant.Name()));
|
||||
Inventory::EquipItem(extraRing,EquipSlot::RING1);
|
||||
REQUIRE(player->HasEnchant(resultEnchant.Name()));
|
||||
Inventory::UnequipItem(EquipSlot::RING1);
|
||||
}
|
||||
Test::InRange(enchantCounts[ItemEnchantInfo::ItemEnchantCategory::GENERAL],{450U,550U});
|
||||
Test::InRange(enchantCounts[ItemEnchantInfo::ItemEnchantCategory::CLASS],{350U,450U});
|
||||
Test::InRange(enchantCounts[ItemEnchantInfo::ItemEnchantCategory::UNIQUE],{50U,150U});
|
||||
}
|
||||
TEST(ItemTests,"EnchantColorTest"){
|
||||
REQUIRE("Item Enchants.General Enchants.Enchant Display Color"_Pixel.n==ItemEnchantInfo::GetEnchant("Health Boost").DisplayCol().n);
|
||||
REQUIRE("Item Enchants.Class Enchants.Enchant Display Color"_Pixel.n==ItemEnchantInfo::GetEnchant("Quickdraw").DisplayCol().n);
|
||||
REQUIRE("Item Enchants.Unique Enchants.Enchant Display Color"_Pixel.n==ItemEnchantInfo::GetEnchant("Magical Protection").DisplayCol().n);
|
||||
}
|
||||
TEST(ItemTests,"CanBeEnchantedTest"){
|
||||
std::weak_ptr<Item>extraRing{Inventory::AddItem("Ring of the Slime King"s)};
|
||||
std::weak_ptr<Item>testArmor{Inventory::AddItem("Test Armor"s)};
|
||||
REQUIRE(!extraRing.lock()->CanBeEnchanted());
|
||||
REQUIRE(!testArmor.lock()->CanBeEnchanted());
|
||||
player->SetMoney(2000U);
|
||||
REQUIRE(!extraRing.lock()->CanBeEnchanted());
|
||||
player->SetMoney(0U);
|
||||
Inventory::AddItem(extraRing.lock()->FragmentName(),"Fragment Enchant Cost"_i[0]);
|
||||
REQUIRE(!extraRing.lock()->CanBeEnchanted());
|
||||
player->SetMoney(2000U);
|
||||
REQUIRE(extraRing.lock()->CanBeEnchanted());
|
||||
extraRing.lock()->ApplyRandomEnchant();
|
||||
REQUIRE(!extraRing.lock()->CanBeEnchanted());
|
||||
Inventory::AddItem(extraRing.lock()->FragmentName(),"Fragment Enchant Cost"_i[0]);
|
||||
REQUIRE(extraRing.lock()->CanBeEnchanted());
|
||||
REQUIRE(uint32_t(2000-"Fragment Enchant Cost"_i[1])==player->GetMoney());
|
||||
}
|
||||
TEST(ItemTests,"UIUpdatesWhenItemsAreReceivedTest"){
|
||||
Inventory::AddItem("Health Potion"s,3);
|
||||
Game::Update(0.f);
|
||||
for(const auto&category:Item::GetItemCategories()|std::views::filter([](const std::string&category){return DATA["ItemCategory"][category].GetString()!="!HIDE";})){
|
||||
const size_t itemCount{Component<RowInventoryScrollableWindowComponent>(MenuType::INVENTORY,std::format("Inventory Display - {}",category))->GetMainComponentCount()};
|
||||
REQUIRE(Inventory::get(category).size()==itemCount);
|
||||
}
|
||||
}
|
||||
TEST(ItemTests,"UIUpdatesWhenGameFileWithItemsIsLoadedTest"){
|
||||
SaveFile::SetSaveFileID(-1);
|
||||
SaveFile::LoadGame();
|
||||
Game::Update(0.f);
|
||||
for(const auto&category:Item::GetItemCategories()|std::views::filter([](const std::string&category){return DATA["ItemCategory"][category].GetString()!="!HIDE";})){
|
||||
const size_t itemCount{Component<RowInventoryScrollableWindowComponent>(MenuType::INVENTORY,std::format("Inventory Display - {}",category))->GetMainComponentCount()};
|
||||
REQUIRE(Inventory::get(category).size()==itemCount);
|
||||
}
|
||||
}
|
||||
TEST(ItemTests,"UIDoesNotUpdateWhenSavingFileFlagIsEnabledTest"){
|
||||
game->savingFile=true;
|
||||
Inventory::AddItem("Health Potion"s,3);
|
||||
for(const auto&category:Item::GetItemCategories()|std::views::filter([](const std::string&category){return DATA["ItemCategory"][category].GetString()!="!HIDE";})){
|
||||
const size_t itemCount{Component<RowInventoryScrollableWindowComponent>(MenuType::INVENTORY,std::format("Inventory Display - {}",category))->GetMainComponentCount()};
|
||||
REQUIRE(size_t(0)==itemCount);
|
||||
}
|
||||
}
|
||||
TEST(ItemTests,"ConsumedLoadoutSlotTest"){
|
||||
Inventory::AddItem("Health Potion"s,4);
|
||||
Inventory::AddItem("Mana Potion"s,2);
|
||||
Inventory::AddItem("Elixir of the Wind"s,1);
|
||||
Inventory::AddItem("Boar Meat"s,3);
|
||||
game->SetLoadoutItem(0,"Health Potion");
|
||||
game->SetLoadoutItem(1,"Mana Potion");
|
||||
game->SetLoadoutItem(2,"Elixir of the Wind");
|
||||
const bool usedItemResult{game->UseLoadoutItem(2)};
|
||||
const bool usedItemResult2{game->UseLoadoutItem(2)};
|
||||
REQUIRE(usedItemResult);
|
||||
REQUIRE(!usedItemResult2);
|
||||
game->SetLoadoutItem(2,"Boar Meat");
|
||||
}
|
||||
TEST(ItemTests,"LoadoutSlotRefillsAfterLevelTest"){
|
||||
Inventory::AddItem("Health Potion"s,100);
|
||||
Inventory::AddItem("Mana Potion"s,100);
|
||||
Inventory::AddItem("Elixir of the Wind"s,100);
|
||||
Inventory::AddItem("Boar Meat"s,3);
|
||||
game->SetLoadoutItem(0,"Health Potion");
|
||||
game->SetLoadoutItem(1,"Mana Potion");
|
||||
game->SetLoadoutItem(2,"Elixir of the Wind");
|
||||
REQUIRE(game->GetLoadoutItem(0).lock()->Amt()==(uint32_t)"Player.Item Loadout Limit"_I);
|
||||
REQUIRE(game->GetLoadoutItem(1).lock()->Amt()==(uint32_t)"Player.Item Loadout Limit"_I);
|
||||
REQUIRE(game->GetLoadoutItem(2).lock()->Amt()==(uint32_t)"Player.Item Loadout Limit"_I);
|
||||
for(int i:std::ranges::iota_view(0U,(uint32_t)"Player.Item Loadout Limit"_I)){
|
||||
game->UseLoadoutItem(0);
|
||||
game->UseLoadoutItem(1);
|
||||
Game::Update(std::max(game->GetLoadoutItem(0).lock()->CooldownTime(),game->GetLoadoutItem(1).lock()->CooldownTime()));
|
||||
}
|
||||
REQUIRE(game->GetLoadoutItem(0).lock()->Amt()==0);
|
||||
REQUIRE(game->GetLoadoutItem(1).lock()->Amt()==0);
|
||||
game->RestockLoadoutItems();
|
||||
REQUIRE(game->GetLoadoutItem(0).lock()->Amt()==(uint32_t)"Player.Item Loadout Limit"_I);
|
||||
REQUIRE(game->GetLoadoutItem(1).lock()->Amt()==(uint32_t)"Player.Item Loadout Limit"_I);
|
||||
REQUIRE(game->GetLoadoutItem(2).lock()->Amt()==(uint32_t)"Player.Item Loadout Limit"_I);
|
||||
}
|
||||
638
Adventures in Lestoria/tests/MonsterTests.cpp
Normal file
638
Adventures in Lestoria/tests/MonsterTests.cpp
Normal file
@ -0,0 +1,638 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#include"AdventuresInLestoria.h"
|
||||
#include"config.h"
|
||||
#include"ItemDrop.h"
|
||||
#include"Tutorial.h"
|
||||
#include"DamageNumber.h"
|
||||
#include"GameHelper.h"
|
||||
#include"SoundEffect.h"
|
||||
#include"Monster.h"
|
||||
|
||||
using namespace olc::utils;
|
||||
|
||||
INCLUDE_MONSTER_DATA
|
||||
INCLUDE_game
|
||||
INCLUDE_GFX
|
||||
INCLUDE_DAMAGENUMBER_LIST
|
||||
INCLUDE_MONSTER_LIST
|
||||
INCLUDE_INITIALIZEGAMECONFIGURATIONS
|
||||
|
||||
class MonsterTests{
|
||||
public:
|
||||
|
||||
std::unique_ptr<AiL>testGame;
|
||||
|
||||
MonsterTests(){
|
||||
SetupTestMonster();
|
||||
SetupMockMap();
|
||||
}
|
||||
~MonsterTests(){
|
||||
testGame->EndGame();
|
||||
testGame->OnUserUpdate(0.f);
|
||||
testGame.reset();
|
||||
}
|
||||
#pragma region Setup Functions
|
||||
//Makes MONSTER_DATA["TestName"] available.
|
||||
void SetupTestMonster(){
|
||||
InitializeGameConfigurations();
|
||||
testGame.reset(new AiL(true));
|
||||
ItemAttribute::Initialize();
|
||||
ItemInfo::InitializeItems();
|
||||
testGame->InitializeGraphics();
|
||||
testGame->InitializeClasses();
|
||||
sig::Animation::InitializeAnimations();
|
||||
Monster::InitializeStrategies();
|
||||
MonsterData::InitializeMonsterData();
|
||||
testGame->InitializeDefaultKeybinds();
|
||||
testGame->InitializePlayer();
|
||||
sig::Animation::SetupPlayerAnimations();
|
||||
Menu::InitializeMenus();
|
||||
Tutorial::Initialize();
|
||||
Stats::InitializeDamageReductionTable();
|
||||
SoundEffect::Initialize();
|
||||
|
||||
GameState::Initialize();
|
||||
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
|
||||
testGame->ResetLevelStates();
|
||||
|
||||
#pragma region Setup a fake test map
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
Game::_SetCurrentLevel("CAMPAIGN_1_1");
|
||||
ItemDrop::ClearDrops();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
#pragma endregion
|
||||
|
||||
MonsterData testMonsterData{"TestName","Test Monster",30,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
testMonsterData.hurtSound="Monster Hurt";
|
||||
MONSTER_DATA["TestName"]=testMonsterData;
|
||||
|
||||
Menu::themes.SetInitialized();
|
||||
GFX.SetInitialized();
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
void SetupMockMap(){
|
||||
game->MAP_DATA.at("CAMPAIGN_1_1")=Map{};
|
||||
ItemDrop::ClearDrops();
|
||||
}
|
||||
#pragma endregion
|
||||
};
|
||||
|
||||
TEST(MonsterTests,"DisplayNameCheck"){
|
||||
REQUIRE("Test Monster"==MONSTER_DATA["TestName"].GetDisplayName());
|
||||
}
|
||||
TEST(MonsterTests,"InternalNameCheck"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
REQUIRE("TestName"==testMonster.GetName());
|
||||
}
|
||||
TEST(MonsterTests,"HealthCheck"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
REQUIRE(testMonster.GetHealth()==testMonster.GetMaxHealth());
|
||||
REQUIRE(testMonster.GetHealth()==30);
|
||||
}
|
||||
TEST(MonsterTests,"Deal5DamageAndNoDamageFlagWork"){
|
||||
Monster&testMonster{game->SpawnMonster({},MONSTER_DATA["TestName"])};
|
||||
Game::Update(0.f);
|
||||
testMonster.Hurt(5,testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
REQUIRE(testMonster.GetHealth()==testMonster.GetMaxHealth()-5);
|
||||
REQUIRE(false==testMonster.HasIframes());
|
||||
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
|
||||
testMonster.Hurt(0,testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
REQUIRE(size_t(2)==DAMAGENUMBER_LIST.size());
|
||||
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
|
||||
testMonster.Hurt(0,testMonster.OnUpperLevel(),testMonster.GetZ(),HurtFlag::NO_DAMAGE_NUMBER);
|
||||
REQUIRE(size_t(2)==DAMAGENUMBER_LIST.size());
|
||||
}
|
||||
TEST(MonsterTests,"Deal5DamageAndDamageSoundEffectsPlay"){
|
||||
Monster&testMonster{game->SpawnMonster({},MONSTER_DATA["TestName"])};
|
||||
testMonster.Hurt(5,testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
REQUIRE(1==SoundEffect::soundsPlayedLog["Monster Hurt"]);
|
||||
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
|
||||
testMonster.Hurt(5,testMonster.OnUpperLevel(),testMonster.GetZ(),HurtFlag::NO_DAMAGE_NUMBER);
|
||||
REQUIRE(1==SoundEffect::soundsPlayedLog["Monster Hurt"]);
|
||||
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
|
||||
testMonster.Hurt(5,testMonster.OnUpperLevel(),testMonster.GetZ(),HurtFlag::DOT);
|
||||
REQUIRE(1==SoundEffect::soundsPlayedLog["Monster Hurt"]);
|
||||
}
|
||||
TEST(MonsterTests,"ZeroDamageResultsInTrue"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
const bool result{testMonster.Hurt(0,testMonster.OnUpperLevel(),testMonster.GetZ())};
|
||||
REQUIRE(true==result);
|
||||
REQUIRE(false==testMonster.HasIframes());
|
||||
}
|
||||
TEST(MonsterTests,"IFrameShouldResultInNoDamage"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.ApplyIframes(0.5f);
|
||||
testMonster.Hurt(5,testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
REQUIRE(testMonster.GetHealth()==testMonster.GetMaxHealth());
|
||||
}
|
||||
TEST(MonsterTests,"BeingInTheAirShouldAvoidAttacksFromTheGround"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.SetZ(2.f);
|
||||
testMonster.Hurt(5,testMonster.OnUpperLevel(),0.f);
|
||||
REQUIRE(testMonster.GetHealth()==testMonster.GetMaxHealth());
|
||||
}
|
||||
TEST(MonsterTests,"MonstersDeal10Damage_NoDamageReduction"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
Monster testMonster2{{},MONSTER_DATA["TestName"]};
|
||||
game->GetPlayer()->Hurt(testMonster.GetAttack(),testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
testMonster2.Hurt(testMonster.GetAttack(),testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
REQUIRE(game->GetPlayer()->GetMaxHealth()-10==game->GetPlayer()->GetHealth());
|
||||
REQUIRE(testMonster2.GetMaxHealth()-10==testMonster2.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"DoubleAttackPctModifierWorks"){
|
||||
Monster buffMonster{{},MONSTER_DATA["TestName"]};
|
||||
buffMonster.AddBuff(BuffType::STAT_UP,5,100._Pct,{ItemAttribute::Get("Attack %")});
|
||||
|
||||
Monster testMonster2{{},MONSTER_DATA["TestName"]};
|
||||
game->GetPlayer()->Hurt(buffMonster.GetAttack(),buffMonster.OnUpperLevel(),buffMonster.GetZ());
|
||||
testMonster2.Hurt(buffMonster.GetAttack(),buffMonster.OnUpperLevel(),buffMonster.GetZ());
|
||||
REQUIRE(game->GetPlayer()->GetMaxHealth()-20==game->GetPlayer()->GetHealth());
|
||||
REQUIRE(testMonster2.GetMaxHealth()-20==testMonster2.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"AttackUpModifierWorks"){
|
||||
Monster buffMonster{{},MONSTER_DATA["TestName"]};
|
||||
buffMonster.AddBuff(BuffType::STAT_UP,5,5.f,{"Attack"});
|
||||
|
||||
Monster testMonster2{{},MONSTER_DATA["TestName"]};
|
||||
game->GetPlayer()->Hurt(buffMonster.GetAttack(),buffMonster.OnUpperLevel(),buffMonster.GetZ());
|
||||
testMonster2.Hurt(buffMonster.GetAttack(),buffMonster.OnUpperLevel(),buffMonster.GetZ());
|
||||
REQUIRE(game->GetPlayer()->GetMaxHealth()-15==game->GetPlayer()->GetHealth());
|
||||
REQUIRE(testMonster2.GetMaxHealth()-15==testMonster2.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"HealthUpModifierWorks"){
|
||||
Monster buffMonster{{},MONSTER_DATA["TestName"]};
|
||||
buffMonster.AddBuff(BuffType::STAT_UP,5,5.f,{"Health"});
|
||||
|
||||
REQUIRE(35==buffMonster.GetMaxHealth());
|
||||
REQUIRE(30==buffMonster.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"AttackUpPctModifierWorks"){
|
||||
Monster buffMonster{{},MONSTER_DATA["TestName"]};
|
||||
buffMonster.AddBuff(BuffType::STAT_UP,5,100.0_Pct,{"Attack %"});
|
||||
|
||||
Monster testMonster2{{},MONSTER_DATA["TestName"]};
|
||||
game->GetPlayer()->Hurt(buffMonster.GetAttack(),buffMonster.OnUpperLevel(),buffMonster.GetZ());
|
||||
testMonster2.Hurt(buffMonster.GetAttack(),buffMonster.OnUpperLevel(),buffMonster.GetZ());
|
||||
REQUIRE(game->GetPlayer()->GetMaxHealth()-20==game->GetPlayer()->GetHealth());
|
||||
REQUIRE(testMonster2.GetMaxHealth()-20==testMonster2.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"MonsterIsConsideredDeadAt0Health"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.Hurt(testMonster.GetMaxHealth(),testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
REQUIRE(true==testMonster.IsDead());
|
||||
}
|
||||
TEST(MonsterTests,"ItemDropSpawnsWhenMonsterIsKilled"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.Hurt(testMonster.GetMaxHealth(),testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
REQUIRE(size_t(1)==ItemDrop::GetDrops().size());
|
||||
}
|
||||
TEST(MonsterTests,"MoveSpdSetCorrectly"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
REQUIRE(2.f==testMonster.GetMoveSpdMult());
|
||||
}
|
||||
TEST(MonsterTests,"SlowdownBuffTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::SLOWDOWN,5.f,0.5f);
|
||||
REQUIRE(1.f==testMonster.GetMoveSpdMult());
|
||||
}
|
||||
TEST(MonsterTests,"SelfInflictedSlowdownTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::SELF_INFLICTED_SLOWDOWN,5.f,0.5f);
|
||||
REQUIRE(1.f==testMonster.GetMoveSpdMult());
|
||||
}
|
||||
TEST(MonsterTests,"SpeedBoostTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::SPEEDBOOST,5.f,0.5f);
|
||||
REQUIRE(3.f==testMonster.GetMoveSpdMult());
|
||||
}
|
||||
TEST(MonsterTests,"LockOnSpeedBoostTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::LOCKON_SPEEDBOOST,5.f,0.5f);
|
||||
REQUIRE(3.f==testMonster.GetMoveSpdMult());
|
||||
}
|
||||
TEST(MonsterTests,"AdditiveMoveSpdBuffsTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::SLOWDOWN,5.f,0.5f);
|
||||
testMonster.AddBuff(BuffType::SPEEDBOOST,5.f,0.75f);
|
||||
REQUIRE(2.5f==testMonster.GetMoveSpdMult());
|
||||
}
|
||||
TEST(MonsterTests,"DamageReductionBuffTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::DAMAGE_REDUCTION,5.f,0.25f);
|
||||
|
||||
testMonster.Hurt(testMonster.GetAttack(),testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
//25% damage reduction should result in 7.5 health taken, When ceiling'd results in 8 health taken.
|
||||
REQUIRE(22==testMonster.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"BarrierBuffTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::BARRIER_DAMAGE_REDUCTION,5.f,0.5f);
|
||||
|
||||
testMonster.Hurt(testMonster.GetAttack(),testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
//50% damage reduction should result in 5 health taken
|
||||
REQUIRE(25==testMonster.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"AdditiveDamageReductionTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::DAMAGE_REDUCTION,5.f,0.25f);
|
||||
testMonster.AddBuff(BuffType::BARRIER_DAMAGE_REDUCTION,5.f,0.5f);
|
||||
|
||||
testMonster.Hurt(testMonster.GetAttack(),testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
//25+50% damage reduction should result in 2.5 health taken. When ceiling'd, results in 3 health taken.
|
||||
REQUIRE(27==testMonster.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"MaximumDamageReductionTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::DAMAGE_REDUCTION,5.f,INFINITY);
|
||||
|
||||
testMonster.Hurt(testMonster.GetAttack(),testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
//At 100% or more damage reduction, the monster should take 0 damage.
|
||||
REQUIRE(30==testMonster.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"TrueDamageTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
|
||||
testMonster._DealTrueDamage(testMonster.GetAttack()*3);
|
||||
REQUIRE(0==testMonster.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"TrueDamageTestWith100PctDamageReduction"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::DAMAGE_REDUCTION,5.f,INFINITY);
|
||||
|
||||
testMonster._DealTrueDamage(testMonster.GetAttack()*3);
|
||||
//Damage reduction should not affect true damage at all.
|
||||
REQUIRE(0==testMonster.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"CriticalRateTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
|
||||
game->GetPlayer()->SetBaseStat(ItemAttribute::Get("Crit Rate"),100.f);
|
||||
|
||||
testMonster.Hurt(5,testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
//If crit rate works 100% of the time, getting hurt should deal crit dmg % more damage (which defaults to 50%). Ceiling 7.5 damage to 8.
|
||||
REQUIRE(22==testMonster.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"CriticalDamageTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
|
||||
game->GetPlayer()->SetBaseStat(ItemAttribute::Get("Crit Rate"),100.f);
|
||||
game->GetPlayer()->SetBaseStat(ItemAttribute::Get("Crit Dmg"),150.f);
|
||||
|
||||
testMonster.Hurt(5,testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
//If crit rate works 100% of the time, getting hurt will deal 150% more damage. Ceiling 12.5 damage to 13.
|
||||
REQUIRE(17==testMonster.GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"ShouldNotDieNormallyTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.diesNormally=false;
|
||||
|
||||
testMonster.Hurt(1000,testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
testMonster.Hurt(1000,testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
testMonster.Hurt(1000,testMonster.OnUpperLevel(),testMonster.GetZ());
|
||||
//Health should continue to remain at 1 and the monster should remain alive if the dies normally flag is false.
|
||||
REQUIRE(1==testMonster.GetHealth());
|
||||
REQUIRE(testMonster.IsAlive());
|
||||
}
|
||||
TEST(MonsterTests,"IllegalDefenseStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"Defense"});
|
||||
FAIL("Adding a Defense buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(MonsterTests,"IllegalMoveSpdStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"Move Spd %"});
|
||||
FAIL("Adding a Move Spd % buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(MonsterTests,"IllegalDefensePctStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"Defense %"});
|
||||
FAIL("Adding a Defense % buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(MonsterTests,"IllegalCDRStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"CDR"});
|
||||
FAIL("Adding a CDR buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(MonsterTests,"IllegalCritRateStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"Crit Rate"});
|
||||
FAIL("Adding a Crit Rate buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(MonsterTests,"IllegalCritDmgStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"Crit Damage"});
|
||||
FAIL("Adding a Crit Damage buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(MonsterTests,"IllegalHPRecoveryPctStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"HP Recovery %"});
|
||||
FAIL("Adding a HP Recovery % buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(MonsterTests,"IllegalHP6RecoveryPctStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"HP6 Recovery %"});
|
||||
FAIL("Adding a HP6 Recovery % buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(MonsterTests,"IllegalHP4RecoveryPctStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"HP4 Recovery %"});
|
||||
FAIL("Adding a HP4 Recovery % buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(MonsterTests,"IllegalDamageReductionStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"Damage Reduction"});
|
||||
FAIL("Adding a Damage Reduction buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(MonsterTests,"IllegalAttackSpdStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"Attack Spd"});
|
||||
FAIL("Adding a Attack Spd buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){};
|
||||
}
|
||||
TEST(MonsterTests,"IllegalManaStatUpBuffCheck"){
|
||||
try{
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::STAT_UP,5.f,5.f,{"Mana"});
|
||||
FAIL("Adding a Mana buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(MonsterTests,"DOTTest"){
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
testMonster.AddBuff(BuffType::DAMAGE_REDUCTION,10.f,100._Pct);
|
||||
testMonster.Hurt(10,testMonster.OnUpperLevel(),testMonster.GetZ(),HurtFlag::DOT);
|
||||
REQUIRE(20==testMonster.GetHealth());
|
||||
testMonster.Update(1.f); //Let time pass so two DOT numbers don't stack up.
|
||||
testMonster.ApplyIframes(0.5f);
|
||||
testMonster.Hurt(10,testMonster.OnUpperLevel(),testMonster.GetZ(),HurtFlag::DOT);
|
||||
REQUIRE(10==testMonster.GetHealth());
|
||||
REQUIRE(2==std::accumulate(DAMAGENUMBER_LIST.begin(),DAMAGENUMBER_LIST.end(),0,[](int count,const std::shared_ptr<DamageNumber>&damageNumber){
|
||||
if(damageNumber->GetType()==DamageNumberType::DOT)return count+1;
|
||||
else return count;
|
||||
})
|
||||
);
|
||||
}
|
||||
TEST(MonsterTests,"TrapperMarkTest"){
|
||||
MonsterData testMonsterData{"TestName","Test Monster",30,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
game->SpawnMonster({},testMonsterData);
|
||||
Game::Update(0.1f); //A monster that is spawned needs to be added to the monster list in the next tick.
|
||||
std::weak_ptr<Monster>testMonster{MONSTER_LIST.front()};
|
||||
|
||||
REQUIRE(uint8_t(0)==testMonster.lock()->GetMarkStacks());
|
||||
|
||||
testMonster.lock()->ApplyMark(7.f,5U);
|
||||
|
||||
game->SetElapsedTime(0.3f);
|
||||
game->OnUserUpdate(0.3f); //A monster that had a mark applied needs to be added as a lock on target in the next tick.
|
||||
|
||||
REQUIRE(uint8_t(5)==testMonster.lock()->GetMarkStacks());
|
||||
|
||||
testMonster.lock()->Hurt(1,testMonster.lock()->OnUpperLevel(),testMonster.lock()->GetZ());
|
||||
|
||||
REQUIRE(uint8_t(5)==testMonster.lock()->GetMarkStacks());
|
||||
|
||||
testMonster.lock()->Hurt(1,testMonster.lock()->OnUpperLevel(),testMonster.lock()->GetZ(),HurtFlag::PLAYER_ABILITY);
|
||||
|
||||
REQUIRE(uint8_t(4)==testMonster.lock()->GetMarkStacks());
|
||||
REQUIRE(22==testMonster.lock()->GetHealth());
|
||||
|
||||
testMonster.lock()->Hurt(1,testMonster.lock()->OnUpperLevel(),testMonster.lock()->GetZ(),HurtFlag::DOT);
|
||||
|
||||
REQUIRE(uint8_t(4)==testMonster.lock()->GetMarkStacks());
|
||||
|
||||
testMonster.lock()->_DealTrueDamage(1);
|
||||
|
||||
REQUIRE(uint8_t(4)==testMonster.lock()->GetMarkStacks());
|
||||
|
||||
testMonster.lock()->Heal(testMonster.lock()->GetMaxHealth()); //Heal the monster so it doesn't die.
|
||||
|
||||
testMonster.lock()->_DealTrueDamage(1,HurtFlag::PLAYER_ABILITY);
|
||||
|
||||
REQUIRE(uint8_t(3)==testMonster.lock()->GetMarkStacks());
|
||||
|
||||
testMonster.lock()->_DealTrueDamage(10,HurtFlag::DOT|HurtFlag::PLAYER_ABILITY);
|
||||
|
||||
REQUIRE(uint8_t(2)==testMonster.lock()->GetMarkStacks());
|
||||
|
||||
testMonster.lock()->Heal(testMonster.lock()->GetMaxHealth());
|
||||
|
||||
testMonster.lock()->TriggerMark();
|
||||
|
||||
REQUIRE(uint8_t(1)==testMonster.lock()->GetMarkStacks());
|
||||
REQUIRE(24==testMonster.lock()->GetHealth());
|
||||
|
||||
game->SetElapsedTime(10.f);
|
||||
testMonster.lock()->Update(10.f);
|
||||
|
||||
REQUIRE(uint8_t(0)==testMonster.lock()->GetMarkStacks());
|
||||
}
|
||||
TEST(MonsterTests,"HurtFailsWhenDead"){
|
||||
MonsterData testMonsterData{"TestName","Test Monster",30,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
Monster&m{game->SpawnMonster({},testMonsterData)};
|
||||
m.Hurt(50,m.OnUpperLevel(),m.GetZ());
|
||||
REQUIRE(m.IsDead());
|
||||
REQUIRE(!m.IsAlive());
|
||||
|
||||
REQUIRE(!m.Hurt(50,m.OnUpperLevel(),m.GetZ()));
|
||||
REQUIRE(!m.Hurt(50,m.OnUpperLevel(),m.GetZ(),HurtFlag::DOT));
|
||||
REQUIRE(!m.Hurt(50,m.OnUpperLevel(),m.GetZ(),HurtFlag::PLAYER_ABILITY));
|
||||
REQUIRE(!m._DealTrueDamage(50));
|
||||
REQUIRE(!m._DealTrueDamage(50==HurtFlag::DOT));
|
||||
REQUIRE(!m._DealTrueDamage(50==HurtFlag::PLAYER_ABILITY));
|
||||
}
|
||||
TEST(MonsterTests,"HurtSucceedsWhenAlive"){
|
||||
MonsterData testMonsterData{"TestName","Test Monster",3000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
Monster&m{game->SpawnMonster({},testMonsterData)};
|
||||
m.Hurt(50,m.OnUpperLevel(),m.GetZ());
|
||||
REQUIRE(!m.IsDead());
|
||||
REQUIRE(m.IsAlive());
|
||||
|
||||
REQUIRE(m.Hurt(50,m.OnUpperLevel(),m.GetZ()));
|
||||
REQUIRE(m.Hurt(50,m.OnUpperLevel(),m.GetZ(),HurtFlag::DOT));
|
||||
REQUIRE(m.Hurt(50,m.OnUpperLevel(),m.GetZ(),HurtFlag::PLAYER_ABILITY));
|
||||
REQUIRE(m._DealTrueDamage(50));
|
||||
REQUIRE(m._DealTrueDamage(50==HurtFlag::DOT));
|
||||
REQUIRE(m._DealTrueDamage(50==HurtFlag::PLAYER_ABILITY));
|
||||
}
|
||||
TEST(MonsterTests,"HurtSucceedsWhenDyingWithExactHealth"){
|
||||
MonsterData testMonsterData{"TestName","Test Monster",50,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
Monster&m{game->SpawnMonster({},testMonsterData)};
|
||||
m.Hurt(50,m.OnUpperLevel(),m.GetZ());
|
||||
REQUIRE(m.IsDead());
|
||||
REQUIRE(!m.IsAlive());
|
||||
m.Heal(50);
|
||||
REQUIRE(m.Hurt(50,m.OnUpperLevel(),m.GetZ()));
|
||||
m.Heal(50);
|
||||
REQUIRE(m.Hurt(50,m.OnUpperLevel(),m.GetZ(),HurtFlag::DOT));
|
||||
m.Heal(50);
|
||||
REQUIRE(m.Hurt(50,m.OnUpperLevel(),m.GetZ(),HurtFlag::PLAYER_ABILITY));
|
||||
m.Heal(50);
|
||||
REQUIRE(m._DealTrueDamage(50));
|
||||
m.Heal(50);
|
||||
REQUIRE(m._DealTrueDamage(50==HurtFlag::DOT));
|
||||
m.Heal(50);
|
||||
REQUIRE(m._DealTrueDamage(50==HurtFlag::PLAYER_ABILITY));
|
||||
}
|
||||
TEST(MonsterTests,"UnconsciousMonsterTest"){
|
||||
Monster&parrot{game->SpawnMonster({},MONSTER_DATA.at("Parrot"))};
|
||||
Game::Update(1.f);
|
||||
REQUIRE(!parrot.IsUnconscious());
|
||||
parrot.Hurt(1,parrot.OnUpperLevel(),parrot.GetZ());
|
||||
REQUIRE(!parrot.IsUnconscious());
|
||||
parrot.Hurt(parrot.GetMaxHealth(),parrot.OnUpperLevel(),parrot.GetZ());
|
||||
REQUIRE(parrot.IsUnconscious());
|
||||
REQUIRE(parrot.IsDead());
|
||||
REQUIRE(parrot.InUndamageableState(parrot.OnUpperLevel(),parrot.GetZ()));
|
||||
Game::Update(MONSTER_DATA.at("Parrot").UnconsciousTime()/2);
|
||||
REQUIRE(parrot.IsUnconscious());
|
||||
REQUIRE(parrot.IsDead());
|
||||
REQUIRE(parrot.InUndamageableState(parrot.OnUpperLevel(),parrot.GetZ()));
|
||||
Game::Update(MONSTER_DATA.at("Parrot").UnconsciousTime()/2);
|
||||
REQUIRE(!parrot.IsUnconscious());
|
||||
REQUIRE(parrot.IsAlive());
|
||||
REQUIRE(!parrot.InUndamageableState(parrot.OnUpperLevel(),parrot.GetZ()));
|
||||
}
|
||||
TEST(MonsterTests,"UnconsciousMonsterHurtTest"){
|
||||
Monster&parrot{game->SpawnMonster({},MONSTER_DATA.at("Parrot"))};
|
||||
Game::Update(1.f);
|
||||
parrot.Hurt(parrot.GetMaxHealth(),parrot.OnUpperLevel(),parrot.GetZ());
|
||||
REQUIRE(parrot.IsUnconscious());
|
||||
}
|
||||
TEST(MonsterTests,"MonsterCollisionRadiusTest"){
|
||||
Monster&parrot{game->SpawnMonster({},MONSTER_DATA.at("Parrot"))};
|
||||
parrot.strategy="[TEST]Run Right"; //Disable default AI for testing collisions
|
||||
Game::Update(1.f);
|
||||
Game::Update(1.f);
|
||||
REQUIRE(parrot.GetOriginalCollisionRadius()==parrot.GetCollisionRadius());
|
||||
|
||||
REQUIRE(int(game->GetPlayer()->GetMaxHealth()-parrot.GetCollisionDamage())==game->GetPlayer()->GetHealth());
|
||||
parrot.SetCollisionRadius(0.f);
|
||||
REQUIRE(0.f==parrot.GetCollisionRadius());
|
||||
game->GetPlayer()->Heal(game->GetPlayer()->GetMaxHealth());
|
||||
game->GetPlayer()->_SetIframes(0.f);
|
||||
parrot.SetPos({});
|
||||
game->GetPlayer()->ForceSetPos({});
|
||||
Game::Update(1.f);
|
||||
REQUIRE(game->GetPlayer()->GetMaxHealth()==game->GetPlayer()->GetHealth());
|
||||
parrot.SetCollisionRadius(parrot.GetOriginalCollisionRadius());
|
||||
Game::Update(1.f);
|
||||
REQUIRE(int(game->GetPlayer()->GetMaxHealth()-parrot.GetCollisionDamage())==game->GetPlayer()->GetHealth());
|
||||
}
|
||||
TEST(MonsterTests,"MonsterCollisionRadiusSizeTest"){
|
||||
Monster&parrot{game->SpawnMonster({},MONSTER_DATA.at("Parrot"))};
|
||||
}
|
||||
TEST(MonsterTests,"MonsterRunRightTest"){
|
||||
Game::LoadLevelWithTMX("TEST_MAP",testGame.get());
|
||||
testGame->GetPlayer()->ForceSetPos({100,100});
|
||||
Monster&boar{game->SpawnMonster({24,24},MONSTER_DATA.at("Boar"))};
|
||||
Game::Update(0.f); // Make sure monster spawns first.
|
||||
boar.strategy="[TEST]Run Right";
|
||||
const vf2d originalBoarPos{boar.GetPos()};
|
||||
Game::Update(0.5f);
|
||||
REQUIRE(originalBoarPos+vf2d{50.f*boar.GetMoveSpdMult(),0.f}==boar.GetPos());
|
||||
}
|
||||
TEST(MonsterTests,"MonsterHasteMoveTest"){
|
||||
Game::LoadLevelWithTMX("TEST_MAP",testGame.get());
|
||||
Monster&parrot{game->SpawnMonster({24,24},MONSTER_DATA.at("Parrot"))};
|
||||
Game::Update(0.f); // Make sure monster spawns first.
|
||||
parrot.strategy="[TEST]Run Right";
|
||||
{
|
||||
const vf2d originalParrotPos{parrot.GetPos()};
|
||||
Game::Update(0.5f);
|
||||
REQUIRE(originalParrotPos+vf2d{50.f*parrot.GetMoveSpdMult(),0.f}==parrot.GetPos());
|
||||
}
|
||||
parrot.AddBuff(BuffType::HASTEN,INFINITE,0.3f);
|
||||
{
|
||||
const vf2d originalParrotPos{parrot.GetPos()};
|
||||
Game::Update(0.5f);
|
||||
REQUIRE(originalParrotPos+vf2d{65.f*parrot.GetMoveSpdMult(),0.f}==parrot.GetPos());
|
||||
}
|
||||
}
|
||||
TEST(MonsterTests,"MonsterManaRecoveryTest"){
|
||||
Monster&fireMage{game->SpawnMonster({24,24},MONSTER_DATA.at("Skeleton Fire Mage"))};
|
||||
std::for_each(MONSTER_DATA["Skeleton Fire Mage"].abilities.begin(),MONSTER_DATA["Skeleton Fire Mage"].abilities.end(),[](MonsterAbilityData&data){
|
||||
data.pctCastChance=0.f; //While testing and running game updates we do not want this ability to go off, so we set the cast percent chance to zero percent.
|
||||
});
|
||||
Game::Update(0.f); // Make sure monster spawns first.
|
||||
const int initialMonsterMP{DATA.GetProperty("Monsters.Skeleton Fire Mage.MP").GetInt()};
|
||||
REQUIRE(fireMage.mp==initialMonsterMP);
|
||||
const float mpRecovery{float(DATA.GetProperty("Monsters.Skeleton Fire Mage.MP Recovery").GetReal())};
|
||||
REQUIRE(fireMage.GetMPRecovery()==mpRecovery);
|
||||
Game::Update(0.f);
|
||||
int newMonsterMP{initialMonsterMP+int(mpRecovery)};
|
||||
REQUIRE(fireMage.mp==newMonsterMP);
|
||||
Game::Update(0.f);
|
||||
REQUIRE(fireMage.mp==newMonsterMP);
|
||||
Game::Update(1.f);
|
||||
newMonsterMP+=int(mpRecovery);
|
||||
REQUIRE(fireMage.mp==newMonsterMP);
|
||||
MONSTER_DATA["TestName"].mpRecovery=0.5f;
|
||||
MONSTER_DATA["TestName"].abilities.emplace_back("Meteor",50,0.0f);
|
||||
Monster&testMonster{game->SpawnMonster({24,24},MONSTER_DATA.at("TestName"))};
|
||||
Game::Update(0.f); // Make sure monster spawns first.
|
||||
REQUIRE(testMonster.mp==0);
|
||||
Game::Update(1.f);
|
||||
REQUIRE(testMonster.mp==0);
|
||||
REQUIRE(testMonster.mpRemainder==0.5f);
|
||||
Game::Update(1.f);
|
||||
REQUIRE(testMonster.mp==1);
|
||||
REQUIRE(testMonster.mpRemainder==0.f);
|
||||
}
|
||||
866
Adventures in Lestoria/tests/PlayerTests.cpp
Normal file
866
Adventures in Lestoria/tests/PlayerTests.cpp
Normal file
@ -0,0 +1,866 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2026 Amy Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include "Tutorial.h"
|
||||
#include <random>
|
||||
#include <format>
|
||||
#include "ItemDrop.h"
|
||||
#include "DamageNumber.h"
|
||||
#include <ranges>
|
||||
#include "GameHelper.h"
|
||||
#include"SoundEffect.h"
|
||||
|
||||
using namespace olc::utils;
|
||||
|
||||
INCLUDE_GFX
|
||||
INCLUDE_ITEM_DATA
|
||||
INCLUDE_DAMAGENUMBER_LIST
|
||||
INCLUDE_INITIALIZEGAMECONFIGURATIONS
|
||||
|
||||
extern std::mt19937 rng;
|
||||
|
||||
class PlayerTests{
|
||||
public:
|
||||
std::unique_ptr<AiL>testGame;
|
||||
InputGroup testKeyboardInput;
|
||||
Player*player;
|
||||
HWButton*testKey;
|
||||
PlayerTests(){
|
||||
InitializeGameConfigurations();
|
||||
rng=std::mt19937{57189U};//Establish a fixed random seed on setup so the exact same results are generated every test run.
|
||||
testGame.reset(new AiL(true));
|
||||
ItemAttribute::Initialize();
|
||||
ItemInfo::InitializeItems();
|
||||
testGame->InitializeGraphics();
|
||||
testGame->InitializeClasses();
|
||||
sig::Animation::InitializeAnimations();
|
||||
testGame->InitializeDefaultKeybinds();
|
||||
testGame->InitializePlayer();
|
||||
sig::Animation::SetupPlayerAnimations();
|
||||
Menu::InitializeMenus();
|
||||
Tutorial::Initialize();
|
||||
Stats::InitializeDamageReductionTable();
|
||||
SoundEffect::Initialize();
|
||||
|
||||
GameState::Initialize();
|
||||
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
|
||||
|
||||
#pragma region Setup a fake test map and test monster
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
ItemDrop::ClearDrops();
|
||||
MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
MONSTER_DATA["TestName"]=testMonsterData;
|
||||
#pragma endregion
|
||||
testGame->ResetLevelStates();
|
||||
|
||||
player=testGame->GetPlayer();
|
||||
//Setup key "0" as a test input
|
||||
testKeyboardInput.AddKeybind(Input{InputType::KEY,0});
|
||||
testKey=testGame->GetKeyboardState(0);
|
||||
testGame->olc_UpdateKeyFocus(true); //Force the game to be "focused" for tests. Required if we want keyboard inputs to work.
|
||||
Menu::themes.SetInitialized();
|
||||
GFX.SetInitialized();
|
||||
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
~PlayerTests(){
|
||||
testGame->EndGame();
|
||||
testGame->OnUserUpdate(0.f);
|
||||
testGame.reset();
|
||||
}
|
||||
};
|
||||
TEST(PlayerTests,"PlayerAlive"){
|
||||
REQUIRE(player->IsAlive());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerTakesDamageAndNoDamageFlagWorks"){
|
||||
player->Hurt(30,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(70==player->GetHealth());
|
||||
REQUIRE(size_t(1)==DAMAGENUMBER_LIST.size());
|
||||
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
|
||||
player->Hurt(0,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(size_t(2)==DAMAGENUMBER_LIST.size());
|
||||
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
|
||||
player->Hurt(0,player->OnUpperLevel(),player->GetZ(),HurtFlag::NO_DAMAGE_NUMBER);
|
||||
REQUIRE(size_t(2)==DAMAGENUMBER_LIST.size());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerTakesDamageSoundEffectsWork"){
|
||||
player->Hurt(30,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(1==SoundEffect::soundsPlayedLog["Player Hit"]);
|
||||
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
|
||||
player->Hurt(20,player->OnUpperLevel(),player->GetZ(),HurtFlag::NO_DAMAGE_NUMBER);
|
||||
REQUIRE(1==SoundEffect::soundsPlayedLog["Player Hit"]);
|
||||
Game::Update(0.1f); //Prevent stacking up damage all on one damage number.
|
||||
player->Hurt(5,player->OnUpperLevel(),player->GetZ(),HurtFlag::DOT);
|
||||
REQUIRE(1==SoundEffect::soundsPlayedLog["Player Hit"]);
|
||||
}
|
||||
TEST(PlayerTests,"PlayerBlockingTakesNoDamage"){
|
||||
player->SetState(State::BLOCK);
|
||||
player->Hurt(30,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(100==player->GetHealth());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerIframesPreventsDamage"){
|
||||
player->ApplyIframes(0.5f);
|
||||
player->Hurt(30,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(100==player->GetHealth());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerConsumesManaOnRightClickAbilityUse"){
|
||||
int abilityManaCost{player->GetRightClickAbility().manaCost};
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
player->CheckAndPerformAbility(player->GetRightClickAbility(),testKeyboardInput);
|
||||
REQUIRE(player->GetMaxMana()-abilityManaCost==player->GetMana());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerConsumesManaOnAbility1Use"){
|
||||
int abilityManaCost{player->GetAbility1().manaCost};
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
player->CheckAndPerformAbility(player->GetAbility1(),testKeyboardInput);
|
||||
REQUIRE(player->GetMaxMana()-abilityManaCost==player->GetMana());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerConsumesManaOnAbility2Use"){
|
||||
int abilityManaCost{player->GetAbility2().manaCost};
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
player->CheckAndPerformAbility(player->GetAbility2(),testKeyboardInput);
|
||||
REQUIRE(player->GetMaxMana()-abilityManaCost==player->GetMana());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerConsumesManaOnAbility3Use"){
|
||||
int abilityManaCost{player->GetAbility3().manaCost};
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
|
||||
REQUIRE(player->GetMaxMana()-abilityManaCost==player->GetMana());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerConsumesManaOnAbility4Use"){
|
||||
int abilityManaCost{player->GetAbility4().manaCost};
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
player->CheckAndPerformAbility(player->GetAbility4(),testKeyboardInput);
|
||||
REQUIRE(player->GetMaxMana()-abilityManaCost==player->GetMana());
|
||||
}
|
||||
TEST(PlayerTests,"WarriorBlockActivatesBlock"){
|
||||
player->GetRightClickAbility().action(player,player->GetPos());
|
||||
REQUIRE(int(State::BLOCK)==int(player->GetState()));
|
||||
}
|
||||
TEST(PlayerTests,"WizardCastDoesNotConsumeManaImmediately"){
|
||||
testGame->ResetPlayerAndChangeClass(WIZARD);
|
||||
player=testGame->GetPlayer(); //The player pointer has been reassigned...
|
||||
//Ability 3 is Meteor, which is a cast. Mana should not be consumed for a spell that begins as a cast.
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
|
||||
REQUIRE(player->GetMaxMana()==player->GetMana());
|
||||
}
|
||||
TEST(PlayerTests,"RangerCastDoesNotConsumeManaImmediately"){
|
||||
testGame->ResetPlayerAndChangeClass(RANGER);
|
||||
player=testGame->GetPlayer(); //The player pointer has been reassigned...
|
||||
//Ability 2 is Charged Shot, which is a cast. Mana should not be consumed for a spell that begins as a cast.
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
player->CheckAndPerformAbility(player->GetAbility2(),testKeyboardInput);
|
||||
REQUIRE(player->GetMaxMana()==player->GetMana());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerTakesDamageWithDamageReductionApplied"){
|
||||
std::weak_ptr<Item>testArmor{Inventory::AddItem("Bone Armor"s)};
|
||||
testArmor.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
|
||||
Inventory::EquipItem(testArmor,EquipSlot::ARMOR);
|
||||
|
||||
//If any of these values change, the armor piece may return a different value and these need to be updated for
|
||||
//BONE ARMOR +10!
|
||||
REQUIRE(72.f==testArmor.lock()->GetStats().A_Read("Defense"));
|
||||
REQUIRE(14.f==testArmor.lock()->GetStats().A_Read("Health"));
|
||||
REQUIRE(7.f==testArmor.lock()->GetStats().A_Read("Attack"));
|
||||
|
||||
player->Hurt(30,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(74==player->GetHealth()); //Even though we are supposed to take 30 damage, damage reduction reduces it to 26 instead. (Random variance is controlled during testing. If this number changes at some point, either the damage formula or the item's stats have changed!)
|
||||
}
|
||||
TEST(PlayerTests,"PlayerSetEffectsAcknowledged"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor"s)};
|
||||
setArmor.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
|
||||
//This gear is supposed to be provide an additional 100 defense, 1000 health, and 100 attack.
|
||||
REQUIRE(100.f+player->GetBaseStat("Defense")==player->GetEquipStat("Defense"));
|
||||
REQUIRE(100.f+player->GetBaseStat("Attack")==player->GetEquipStat("Attack"));
|
||||
REQUIRE(1000.f+player->GetBaseStat("Health")==player->GetEquipStat("Health"));
|
||||
}
|
||||
TEST(PlayerTests,"PlayerSetEffectsAcknowledged2"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
|
||||
setArmor.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
|
||||
//This gear is supposed to be provide an additional 100% defense, 100% Attack, 100% Move Spd, 100% CDR, 100% Crit Rate, 100% Crit Dmg, 100% Health %, 100% HP/6 Recovery
|
||||
REQUIRE(100.f+player->GetBaseStat("Defense %")==player->GetEquipStat("Defense %"));
|
||||
REQUIRE(100.f+player->GetBaseStat("Attack %")==player->GetEquipStat("Attack %"));
|
||||
REQUIRE(100.f+player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
|
||||
REQUIRE(100.f+player->GetBaseStat("CDR")==player->GetEquipStat("CDR"));
|
||||
REQUIRE(100.f+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
|
||||
REQUIRE(100.f+player->GetBaseStat("Crit Dmg")==player->GetEquipStat("Crit Dmg"));
|
||||
REQUIRE(100.f+player->GetBaseStat("Health %")==player->GetEquipStat("Health %"));
|
||||
REQUIRE(100.f+player->GetBaseStat("HP6 Recovery %")==player->GetEquipStat("HP6 Recovery %"));
|
||||
}
|
||||
TEST(PlayerTests,"PlayerSetEffectsAcknowledged3"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
|
||||
setArmor.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
|
||||
//This gear is supposed to be provide an additional 100% HP/4 Recovery, 100% Damage Reduction
|
||||
REQUIRE(100.f+player->GetBaseStat("HP4 Recovery %")==player->GetEquipStat("HP4 Recovery %"));
|
||||
REQUIRE(100.f+player->GetBaseStat("Damage Reduction")==player->GetEquipStat("Damage Reduction"));
|
||||
}
|
||||
TEST(PlayerTests,"PlayerSetEffectsAcknowledged4"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor4"s)};
|
||||
setArmor.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
|
||||
//This gear is supposed to be provide an additional 100% HP/s Recovery, 50% Attack Spd, and 100 More Base Mana.
|
||||
REQUIRE(100.f+player->GetBaseStat("HP Recovery %")==player->GetEquipStat("HP Recovery %"));
|
||||
REQUIRE(50.f+player->GetBaseStat("Attack Spd")==player->GetEquipStat("Attack Spd"));
|
||||
REQUIRE(100.f+player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
|
||||
}
|
||||
TEST(PlayerTests,"MultiPieceSetEffectsWork"){
|
||||
std::weak_ptr<Item>testArmor{Inventory::AddItem("Bone Armor"s)};
|
||||
std::weak_ptr<Item>testHeadpiece{Inventory::AddItem("Bone Helmet"s)};
|
||||
std::weak_ptr<Item>testLeggings{Inventory::AddItem("Bone Pants"s)};
|
||||
std::weak_ptr<Item>testGloves{Inventory::AddItem("Bone Gloves"s)};
|
||||
|
||||
REQUIRE(player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
|
||||
REQUIRE(player->GetBaseStat("Crit Dmg")==player->GetEquipStat("Crit Dmg"));
|
||||
|
||||
Inventory::EquipItem(testArmor,EquipSlot::ARMOR);
|
||||
Inventory::EquipItem(testHeadpiece,EquipSlot::HELMET);
|
||||
|
||||
REQUIRE(5+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
|
||||
REQUIRE(player->GetBaseStat("Crit Dmg")==player->GetEquipStat("Crit Dmg"));
|
||||
|
||||
Inventory::UnequipItem(EquipSlot::ARMOR);
|
||||
REQUIRE(player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
|
||||
REQUIRE(player->GetBaseStat("Crit Dmg")==player->GetEquipStat("Crit Dmg"));
|
||||
|
||||
Inventory::EquipItem(testArmor,EquipSlot::ARMOR);
|
||||
Inventory::EquipItem(testLeggings,EquipSlot::PANTS);
|
||||
Inventory::EquipItem(testGloves,EquipSlot::GLOVES);
|
||||
REQUIRE(5+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
|
||||
REQUIRE(7+player->GetBaseStat("Crit Dmg")==player->GetEquipStat("Crit Dmg"));
|
||||
}
|
||||
TEST(PlayerTests,"AccessoriesWork"){
|
||||
std::weak_ptr<Item>testRing{Inventory::AddItem("Bird's Treasure"s)};
|
||||
std::weak_ptr<Item>testRing2{Inventory::AddItem("Bird's Treasure"s)};
|
||||
|
||||
REQUIRE(3.f==testRing.lock()->RandomStats().A_Read("Move Spd %"));
|
||||
REQUIRE(2.f==testRing.lock()->RandomStats().A_Read("Crit Rate"));
|
||||
REQUIRE(5.f==testRing.lock()->RandomStats().A_Read("Mana"));
|
||||
|
||||
REQUIRE(2.f==testRing2.lock()->RandomStats().A_Read("Move Spd %"));
|
||||
REQUIRE(2.f==testRing2.lock()->RandomStats().A_Read("Crit Rate"));
|
||||
REQUIRE(2.f==testRing2.lock()->RandomStats().A_Read("Mana"));
|
||||
|
||||
REQUIRE((testRing.lock()->RandomStats().A_Read("Move Spd %")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Move Spd %")&&
|
||||
testRing.lock()->RandomStats().A_Read("Move Spd %")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Move Spd %")));
|
||||
REQUIRE((testRing.lock()->RandomStats().A_Read("Crit Rate")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Crit Rate")&&
|
||||
testRing.lock()->RandomStats().A_Read("Crit Rate")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Crit Rate")));
|
||||
REQUIRE((testRing.lock()->RandomStats().A_Read("Mana")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Mana")&&
|
||||
testRing.lock()->RandomStats().A_Read("Mana")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Mana")));
|
||||
|
||||
REQUIRE((testRing2.lock()->RandomStats().A_Read("Move Spd %")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Move Spd %")&&
|
||||
testRing2.lock()->RandomStats().A_Read("Move Spd %")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Move Spd %")));
|
||||
REQUIRE((testRing2.lock()->RandomStats().A_Read("Crit Rate")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Crit Rate")&&
|
||||
testRing2.lock()->RandomStats().A_Read("Crit Rate")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Crit Rate")));
|
||||
REQUIRE((testRing2.lock()->RandomStats().A_Read("Mana")>=ITEM_DATA.at("Bird's Treasure"s).GetMinStats().A_Read("Mana")&&
|
||||
testRing2.lock()->RandomStats().A_Read("Mana")<=ITEM_DATA.at("Bird's Treasure"s).GetMaxStats().A_Read("Mana")));
|
||||
|
||||
//Ensure stats are default.
|
||||
REQUIRE(player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
|
||||
REQUIRE(player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
|
||||
REQUIRE(player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
|
||||
|
||||
Inventory::EquipItem(testRing,EquipSlot::RING1);
|
||||
REQUIRE(3+player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
|
||||
REQUIRE(2+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
|
||||
REQUIRE(5+player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
|
||||
|
||||
//Equipping to same slot should undo the previous stats and apply the new ring's stats.
|
||||
Inventory::EquipItem(testRing2,EquipSlot::RING1);
|
||||
REQUIRE(2+player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
|
||||
REQUIRE(2+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
|
||||
REQUIRE(2+player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
|
||||
|
||||
Inventory::UnequipItem(EquipSlot::RING1);
|
||||
//Ensure stats are default again.
|
||||
REQUIRE(player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
|
||||
REQUIRE(player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
|
||||
REQUIRE(player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
|
||||
|
||||
Inventory::EquipItem(testRing,EquipSlot::RING1);
|
||||
Inventory::EquipItem(testRing2,EquipSlot::RING2);
|
||||
REQUIRE(5+player->GetBaseStat("Move Spd %")==player->GetEquipStat("Move Spd %"));
|
||||
REQUIRE(4+player->GetBaseStat("Crit Rate")==player->GetEquipStat("Crit Rate"));
|
||||
REQUIRE(7+player->GetBaseStat("Mana")==player->GetEquipStat("Mana"));
|
||||
}
|
||||
TEST(PlayerTests,"FlatDefenseStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor"s)};
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
player->Hurt(100,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(17==player->GetHealth());
|
||||
}
|
||||
TEST(PlayerTests,"HealthStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor"s)};
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(1000+player->GetBaseStat("Health")==float(player->GetMaxHealth()));
|
||||
}
|
||||
TEST(PlayerTests,"HealthStatUpBuffCheck"){
|
||||
Game::AddBuffToPlayer(BuffType::STAT_UP,5.f,1000.f,{"Health"});
|
||||
REQUIRE(1000+player->GetBaseStat("Health")==float(player->GetMaxHealth()));
|
||||
}
|
||||
TEST(PlayerTests,"HealthPctStatUpBuffCheck"){
|
||||
Game::AddBuffToPlayer(BuffType::STAT_UP,5.f,1000.0_Pct,{"Health %"});
|
||||
REQUIRE(1000+player->GetBaseStat("Health")==float(player->GetMaxHealth()));
|
||||
}
|
||||
TEST(PlayerTests,"IllegalCritRateStatUpBuffCheck"){
|
||||
try{
|
||||
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Crit Rate"});
|
||||
FAIL("Adding a Crit Rate buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(PlayerTests,"IllegalCritDmgStatUpBuffCheck"){
|
||||
try{
|
||||
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Crit Damage"});
|
||||
FAIL("Adding a Crit Damage buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(PlayerTests,"IllegalHPRecoveryPctStatUpBuffCheck"){
|
||||
try{
|
||||
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"HP Recovery %"});
|
||||
FAIL("Adding a HP Recovery % buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(PlayerTests,"IllegalHP6RecoveryPctStatUpBuffCheck"){
|
||||
try{
|
||||
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"HP6 Recovery %"});
|
||||
FAIL("Adding a HP6 Recovery % buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(PlayerTests,"IllegalHP4RecoveryPctStatUpBuffCheck"){
|
||||
try{
|
||||
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"HP4 Recovery %"});
|
||||
FAIL("Adding a HP4 Recovery % buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(PlayerTests,"IllegalDamageReductionStatUpBuffCheck"){
|
||||
try{
|
||||
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Damage Reduction"});
|
||||
FAIL("Adding a Damage Reduction buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(PlayerTests,"IllegalAttackSpdStatUpBuffCheck"){
|
||||
try{
|
||||
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Attack Spd"});
|
||||
FAIL("Adding a Attack Spd buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){};
|
||||
}
|
||||
TEST(PlayerTests,"IllegalManaStatUpBuffCheck"){
|
||||
try{
|
||||
player->AddBuff(BuffType::STAT_UP,5.f,1000.0_Pct,{"Mana"});
|
||||
FAIL("Adding a Mana buff succeeded! This should NOT be allowed!");
|
||||
}catch(std::exception&e){}
|
||||
}
|
||||
TEST(PlayerTests,"AttackStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor"s)};
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(100+player->GetBaseStat("Attack")==float(player->GetAttack()));
|
||||
}
|
||||
TEST(PlayerTests,"DefensePctStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(player->GetBaseStat("Defense")==float(player->GetDefense()));
|
||||
|
||||
std::weak_ptr<Item>bonePants{Inventory::AddItem("Bone Pants"s)};
|
||||
bonePants.lock()->enhancementLevel="Item.Item Max Enhancement Level"_I; //Force enhance the item to the max enhancement level.
|
||||
Inventory::EquipItem(bonePants,EquipSlot::PANTS);
|
||||
REQUIRE(122.f+player->GetBaseStat("Defense")==float(player->GetDefense()));
|
||||
|
||||
Inventory::UnequipItem(EquipSlot::ARMOR);
|
||||
player->Hurt(100,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(13==player->GetHealth());
|
||||
player->Heal(87); //Back to 100 Health.
|
||||
LOG(std::format("Player Health is now {}",player->GetHealth()));
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
player->Hurt(100,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(36==player->GetHealth());
|
||||
}
|
||||
TEST(PlayerTests,"AttackPctStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
|
||||
Monster testMonster{{},MONSTER_DATA["TestName"]};
|
||||
|
||||
testMonster.Hurt(player->GetAttack(),player->OnUpperLevel(),player->GetZ());
|
||||
const int damageDealt{testMonster.GetMaxHealth()-testMonster.GetHealth()};
|
||||
|
||||
testMonster.Heal(testMonster.GetMaxHealth());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(player->GetBaseStat("Attack")*2==float(player->GetAttack()));
|
||||
|
||||
testMonster.Hurt(player->GetAttack(),player->OnUpperLevel(),player->GetZ());
|
||||
const int enhancedDamageDealt{testMonster.GetMaxHealth()-testMonster.GetHealth()};
|
||||
REQUIRE(enhancedDamageDealt==damageDealt*5);
|
||||
}
|
||||
TEST(PlayerTests,"MoveSpdPctStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
|
||||
|
||||
REQUIRE(1.f==player->GetMoveSpdMult());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(2.f==player->GetMoveSpdMult());
|
||||
}
|
||||
TEST(PlayerTests,"CDRStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
|
||||
|
||||
REQUIRE(0.f==player->GetCooldownReductionPct());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(1.f==player->GetCooldownReductionPct());
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
player->CheckAndPerformAbility(player->GetRightClickAbility(),testKeyboardInput);
|
||||
player->CheckAndPerformAbility(player->GetAbility1(),testKeyboardInput);
|
||||
player->CheckAndPerformAbility(player->GetAbility2(),testKeyboardInput);
|
||||
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
|
||||
player->CheckAndPerformAbility(player->GetAbility4(),testKeyboardInput);
|
||||
|
||||
Inventory::AddItem("Health Potion"s);
|
||||
Inventory::AddItem("Berries"s);
|
||||
Inventory::AddItem("Mana Potion"s);
|
||||
game->SetLoadoutItem(0,"Health Potion");
|
||||
game->SetLoadoutItem(1,"Berries");
|
||||
game->SetLoadoutItem(2,"Mana Potion");
|
||||
|
||||
player->CheckAndPerformAbility(player->GetItem1(),testKeyboardInput);
|
||||
player->CheckAndPerformAbility(player->GetItem2(),testKeyboardInput);
|
||||
player->CheckAndPerformAbility(player->GetItem3(),testKeyboardInput);
|
||||
|
||||
game->SetElapsedTime(0.01f); //Force elapsed time value.
|
||||
game->OnUserUpdate(0.01f); //Let 0.01 seconds go by. All abilities should be off cooldown.
|
||||
REQUIRE(0.f==player->GetRightClickAbility().cooldown);
|
||||
REQUIRE(0.f==player->GetAbility1().cooldown);
|
||||
REQUIRE(0.f==player->GetAbility2().cooldown);
|
||||
REQUIRE(0.f==player->GetAbility3().cooldown);
|
||||
REQUIRE(0.f==player->GetAbility4().cooldown);
|
||||
REQUIRE(0.f!=player->GetItem1().cooldown);
|
||||
REQUIRE(0.f!=player->GetItem2().cooldown);
|
||||
REQUIRE(0.f!=player->GetItem3().cooldown);
|
||||
}
|
||||
TEST(PlayerTests,"CritRateStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
|
||||
|
||||
REQUIRE(0.f==player->GetCritRatePct());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(1.f==player->GetCritRatePct());
|
||||
}
|
||||
TEST(PlayerTests,"CritDmgStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
|
||||
|
||||
REQUIRE(0.5f==player->GetCritDmgPct());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(1.5f==player->GetCritDmgPct());
|
||||
}
|
||||
TEST(PlayerTests,"HealthPctStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
|
||||
|
||||
REQUIRE(100==player->GetHealth());
|
||||
REQUIRE(100==player->GetMaxHealth());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(100==player->GetHealth());
|
||||
REQUIRE(200==player->GetMaxHealth());
|
||||
}
|
||||
TEST(PlayerTests,"HP6RecoveryStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
|
||||
|
||||
REQUIRE(0.0_Pct==player->GetHP6RecoveryPct());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(100.0_Pct==player->GetHP6RecoveryPct());
|
||||
}
|
||||
TEST(PlayerTests,"HP4RecoveryStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
|
||||
|
||||
REQUIRE(0.0_Pct==player->GetHP4RecoveryPct());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(100.0_Pct==player->GetHP4RecoveryPct());
|
||||
}
|
||||
TEST(PlayerTests,"DamageReductionStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
|
||||
REQUIRE(0.0_Pct==player->GetDamageReductionFromBuffs());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(75.0_Pct==player->GetDamageReductionFromBuffs());
|
||||
}
|
||||
TEST(PlayerTests,"HPRecoveryStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor4"s)};
|
||||
|
||||
REQUIRE(0.0_Pct==player->GetHPRecoveryPct());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(100.0_Pct==player->GetHPRecoveryPct());
|
||||
}
|
||||
TEST(PlayerTests,"AttackSpeedStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor4"s)};
|
||||
|
||||
REQUIRE(0.f==player->GetAttackRecoveryRateReduction());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(50.f==player->GetAttackRecoveryRateReduction());
|
||||
}
|
||||
TEST(PlayerTests,"ManaStatEquipCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor4"s)};
|
||||
|
||||
REQUIRE(100==player->GetMana());
|
||||
REQUIRE(100==player->GetMaxMana());
|
||||
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(100==player->GetMana());
|
||||
REQUIRE(200==player->GetMaxMana());
|
||||
}
|
||||
TEST(PlayerTests,"HP6RecoveryTest"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor2"s)};
|
||||
game->SetElapsedTime(0.1f);
|
||||
game->OnUserUpdate(0.1f); //Advance the game by 0.1s so that all healing ticks occur at least once.
|
||||
//Hurt the player for most of their health.
|
||||
player->Hurt(player->GetMaxHealth()-1,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(1==player->GetHealth());
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(100.0_Pct==player->GetHP6RecoveryPct());
|
||||
|
||||
game->SetElapsedTime(3.f);
|
||||
game->OnUserUpdate(3.f); //Wait 3 seconds. The player shouldn't be healed yet.
|
||||
REQUIRE(1==player->GetHealth());
|
||||
game->SetElapsedTime(3.f);
|
||||
game->OnUserUpdate(3.f); //Wait 3 more seconds. The player should be healed now.
|
||||
REQUIRE(player->GetMaxHealth()==player->GetHealth());
|
||||
}
|
||||
TEST(PlayerTests,"HP4RecoveryTest"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
|
||||
game->SetElapsedTime(0.1f);
|
||||
game->OnUserUpdate(0.1f); //Advance the game by 0.1s so that all healing ticks occur at least once.
|
||||
//Hurt the player for most of their health.
|
||||
player->Hurt(player->GetMaxHealth()-1,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(1==player->GetHealth());
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(100.0_Pct==player->GetHP4RecoveryPct());
|
||||
|
||||
game->SetElapsedTime(2.f);
|
||||
game->OnUserUpdate(2.f); //Wait 2 seconds. The player shouldn't be healed yet.
|
||||
REQUIRE(1==player->GetHealth());
|
||||
game->SetElapsedTime(2.f);
|
||||
game->OnUserUpdate(2.f); //Wait 2 more seconds. The player should be healed now.
|
||||
REQUIRE(player->GetMaxHealth()==player->GetHealth());
|
||||
}
|
||||
TEST(PlayerTests,"HPRecoveryTest"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor4"s)};
|
||||
game->SetElapsedTime(0.1f);
|
||||
game->OnUserUpdate(0.1f); //Advance the game by 0.1s so that all healing ticks occur at least once.
|
||||
//Hurt the player for most of their health.
|
||||
player->Hurt(player->GetMaxHealth()-1,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(1==player->GetHealth());
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR);
|
||||
REQUIRE(100.0_Pct==player->GetHPRecoveryPct());
|
||||
|
||||
game->SetElapsedTime(0.5f);
|
||||
game->OnUserUpdate(0.5f); //Wait 0.5 seconds. The player shouldn't be healed yet.
|
||||
REQUIRE(1==player->GetHealth());
|
||||
game->SetElapsedTime(0.5f);
|
||||
game->OnUserUpdate(0.5f); //Wait 0.5 more seconds. The player should be healed now.
|
||||
REQUIRE(player->GetMaxHealth()==player->GetHealth());
|
||||
}
|
||||
TEST(PlayerTests,"AdrenalineRushSkillBuffTest"){
|
||||
testGame->ResetPlayerAndChangeClass(THIEF);
|
||||
player=testGame->GetPlayer(); //The player pointer has been reassigned...
|
||||
REQUIRE(1.f==player->GetMoveSpdMult());
|
||||
REQUIRE(0.f==player->GetAttackRecoveryRateReduction());
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
|
||||
Game::Update(0.f);
|
||||
REQUIRE(player->GetBuffs(BuffType::ADRENALINE_RUSH).size()>0);
|
||||
REQUIRE(1.1f==player->GetMoveSpdMult());
|
||||
REQUIRE(0.105f==player->GetAttackRecoveryRateReduction());
|
||||
}
|
||||
TEST(PlayerTests,"TrueDamageCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR); //Equip an item with 100% damage reduction.
|
||||
player->Hurt(20,player->OnUpperLevel(),player->GetZ(),TrueDamageFlag::IGNORE_DAMAGE_RULES);
|
||||
REQUIRE(80==player->GetHealth());
|
||||
player->ApplyIframes(0.5f);
|
||||
player->Hurt(20,player->OnUpperLevel(),player->GetZ(),TrueDamageFlag::IGNORE_DAMAGE_RULES);
|
||||
REQUIRE(60==player->GetHealth());
|
||||
}
|
||||
TEST(PlayerTests,"DOTDamageCheck"){
|
||||
std::weak_ptr<Item>setArmor{Inventory::AddItem("Test Armor3"s)};
|
||||
Inventory::EquipItem(setArmor,EquipSlot::ARMOR); //Equip an item with 100% damage reduction.
|
||||
player->Hurt(20,player->OnUpperLevel(),player->GetZ(),HurtFlag::DOT);
|
||||
REQUIRE(80==player->GetHealth());
|
||||
REQUIRE(1==std::accumulate(DAMAGENUMBER_LIST.begin(),DAMAGENUMBER_LIST.end(),0,[](int count,const std::shared_ptr<DamageNumber>&damageNumber){
|
||||
if(damageNumber->GetType()==DamageNumberType::DOT)return count+1;
|
||||
else return count;
|
||||
})
|
||||
);
|
||||
player->Update(1.0f);//Let some time pass so two DOT numbers don't stack up.
|
||||
player->ApplyIframes(0.5f);
|
||||
player->Hurt(20,player->OnUpperLevel(),player->GetZ(),HurtFlag::DOT);
|
||||
REQUIRE(80==player->GetHealth());
|
||||
REQUIRE(2==std::accumulate(DAMAGENUMBER_LIST.begin(),DAMAGENUMBER_LIST.end(),0,[](int count,const std::shared_ptr<DamageNumber>&damageNumber){
|
||||
if(damageNumber->GetType()==DamageNumberType::DOT)return count+1;
|
||||
else return count;
|
||||
})
|
||||
);
|
||||
}
|
||||
TEST(PlayerTests,"HasEnchantCheck"){
|
||||
std::weak_ptr<Item>slimeKingRing{Inventory::AddItem("Ring of the Slime King"s)};
|
||||
Inventory::EquipItem(slimeKingRing,EquipSlot::RING1);
|
||||
slimeKingRing.lock()->_EnchantItem("Emergency Recovery"sv);
|
||||
REQUIRE(player->HasEnchant("Emergency Recovery"));
|
||||
Inventory::EquipItem(slimeKingRing,EquipSlot::RING2);
|
||||
REQUIRE(player->HasEnchant("Emergency Recovery"));
|
||||
Inventory::EquipItem(slimeKingRing,EquipSlot::RING1);
|
||||
slimeKingRing.lock()->_EnchantItem("Reaper of Souls"sv);
|
||||
REQUIRE(player->HasEnchant("Reaper of Souls"));
|
||||
Inventory::EquipItem(slimeKingRing,EquipSlot::RING2);
|
||||
REQUIRE(player->HasEnchant("Reaper of Souls"));
|
||||
Inventory::EquipItem(slimeKingRing,EquipSlot::RING1);
|
||||
slimeKingRing.lock()->_EnchantItem("Attack Boost"sv);
|
||||
REQUIRE(player->HasEnchant("Attack Boost"));
|
||||
Inventory::EquipItem(slimeKingRing,EquipSlot::RING2);
|
||||
REQUIRE(player->HasEnchant("Attack Boost"));
|
||||
|
||||
std::weak_ptr<Item>leatherHelmet{Inventory::AddItem("Leather Helmet"s)};
|
||||
std::weak_ptr<Item>leatherArmor{Inventory::AddItem("Leather Armor"s)};
|
||||
std::weak_ptr<Item>leatherPants{Inventory::AddItem("Leather Pants"s)};
|
||||
std::weak_ptr<Item>leatherGloves{Inventory::AddItem("Leather Gloves"s)};
|
||||
std::weak_ptr<Item>leatherShoes{Inventory::AddItem("Leather Shoes"s)};
|
||||
std::weak_ptr<Item>woodenSword{Inventory::AddItem("Wooden Sword"s)};
|
||||
|
||||
Inventory::EquipItem(leatherHelmet,EquipSlot::HELMET);
|
||||
Inventory::EquipItem(leatherArmor,EquipSlot::ARMOR);
|
||||
Inventory::EquipItem(leatherPants,EquipSlot::PANTS);
|
||||
Inventory::EquipItem(leatherGloves,EquipSlot::GLOVES);
|
||||
Inventory::EquipItem(leatherShoes,EquipSlot::SHOES);
|
||||
Inventory::EquipItem(woodenSword,EquipSlot::WEAPON);
|
||||
|
||||
leatherHelmet.lock()->_EnchantItem("Wizard's Soul"sv);
|
||||
REQUIRE(player->HasEnchant("Wizard's Soul"));
|
||||
leatherArmor.lock()->_EnchantItem("Ability Haste"sv);
|
||||
REQUIRE(player->HasEnchant("Ability Haste"));
|
||||
leatherPants.lock()->_EnchantItem("Improved Ground Slam"sv);
|
||||
REQUIRE(player->HasEnchant("Improved Ground Slam"));
|
||||
leatherGloves.lock()->_EnchantItem("Battle Shout"sv);
|
||||
REQUIRE(player->HasEnchant("Battle Shout"));
|
||||
leatherShoes.lock()->_EnchantItem("Attack Boost"sv);
|
||||
Inventory::UnequipItem(EquipSlot::RING2);
|
||||
REQUIRE(player->HasEnchant("Attack Boost"));
|
||||
woodenSword.lock()->_EnchantItem("Mana Pool"sv);
|
||||
REQUIRE(player->HasEnchant("Mana Pool"));
|
||||
|
||||
Inventory::UnequipItem(EquipSlot::HELMET);
|
||||
Inventory::UnequipItem(EquipSlot::ARMOR);
|
||||
Inventory::UnequipItem(EquipSlot::PANTS);
|
||||
Inventory::UnequipItem(EquipSlot::GLOVES);
|
||||
Inventory::UnequipItem(EquipSlot::SHOES);
|
||||
Inventory::UnequipItem(EquipSlot::WEAPON);
|
||||
Inventory::UnequipItem(EquipSlot::RING1);
|
||||
Inventory::UnequipItem(EquipSlot::RING2);
|
||||
|
||||
REQUIRE(!player->HasEnchant("Emergency Recovery"));
|
||||
REQUIRE(!player->HasEnchant("Reaper of Souls"));
|
||||
REQUIRE(!player->HasEnchant("Attack Boost"));
|
||||
REQUIRE(!player->HasEnchant("Wizard's Soul"));
|
||||
REQUIRE(!player->HasEnchant("Ability Haste"));
|
||||
REQUIRE(!player->HasEnchant("Improved Ground Slam"));
|
||||
REQUIRE(!player->HasEnchant("Battle Shout"));
|
||||
REQUIRE(!player->HasEnchant("Attack Boost"));
|
||||
REQUIRE(!player->HasEnchant("Mana Pool"));
|
||||
}
|
||||
TEST(PlayerTests,"AutoAttackReductionFunctionCheck"){
|
||||
REQUIRE(0.f==player->GetAutoAttackTimer());
|
||||
player->AutoAttack();
|
||||
REQUIRE("Warrior.Auto Attack.Cooldown"_F==player->GetAutoAttackTimer());
|
||||
player->ReduceAutoAttackTimer(0.2f);
|
||||
REQUIRE("Warrior.Auto Attack.Cooldown"_F-0.2f==player->GetAutoAttackTimer());
|
||||
}
|
||||
TEST(PlayerTests,"CooldownChargesCheck"){
|
||||
player->GetAbility4()=Ranger::ability1;
|
||||
|
||||
for(const std::reference_wrapper<Ability>&a:player->GetAbilities()){
|
||||
if(a.get().name=="???")continue;
|
||||
REQUIRE(uint8_t(1)==a.get().charges);
|
||||
REQUIRE(0.f==a.get().cooldown);
|
||||
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
player->CheckAndPerformAbility(a.get(),testKeyboardInput);
|
||||
REQUIRE(uint8_t(0)==a.get().charges);
|
||||
REQUIRE(a.get().COOLDOWN_TIME==a.get().cooldown);
|
||||
player->RestoreMana(100);
|
||||
player->SetState(State::NORMAL);
|
||||
player->CheckAndPerformAbility(a.get(),testKeyboardInput);
|
||||
a.get().MAX_CHARGES=5;
|
||||
for(int i:std::ranges::iota_view(0,5)){
|
||||
testGame->SetElapsedTime(a.get().COOLDOWN_TIME);
|
||||
testGame->OnUserUpdate(a.get().COOLDOWN_TIME);
|
||||
|
||||
REQUIRE(uint8_t(i+1)==a.get().charges);
|
||||
if(i!=4)REQUIRE(a.get().COOLDOWN_TIME==a.get().cooldown);
|
||||
else REQUIRE(0.f==a.get().cooldown);
|
||||
}
|
||||
player->RestoreMana(100);
|
||||
player->SetState(State::NORMAL);
|
||||
}
|
||||
}
|
||||
TEST(PlayerTests,"ChargesEquipBehaviorCheck"){
|
||||
testGame->ResetPlayerAndChangeClass(RANGER);
|
||||
player=testGame->GetPlayer();
|
||||
player->GetAbility3().charges=3;
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
testGame->SetElapsedTime(0.25f);
|
||||
testGame->OnUserUpdate(0.25f);
|
||||
REQUIRE(uint8_t(1)==player->GetAbility3().charges);
|
||||
player->CheckAndPerformAbility(player->GetAbility3(),testKeyboardInput);
|
||||
REQUIRE(uint8_t(0)==player->GetAbility3().charges);
|
||||
}
|
||||
TEST(PlayerTests,"CooldownEquipBehaviorCheck"){
|
||||
testGame->ResetPlayerAndChangeClass(RANGER);
|
||||
player=testGame->GetPlayer();
|
||||
float oldCooldownTime{player->GetAbility3().GetCooldownTime()};
|
||||
player->GetAbility3().cooldown=player->GetAbility3().GetCooldownTime();
|
||||
std::weak_ptr<Item>nullRing{Inventory::AddItem("Null Ring"s)};
|
||||
Inventory::EquipItem(nullRing,EquipSlot::RING1);
|
||||
nullRing.lock()->_EnchantItem("Multi-Multishot"sv);
|
||||
testKey->bHeld=true; //Force the key to be held down for testing purposes.
|
||||
REQUIRE(player->GetAbility3().GetCooldownTime()==oldCooldownTime-oldCooldownTime*"Multi-Multishot"_ENC["COOLDOWN REDUCTION PCT"]/100.f);
|
||||
testGame->SetElapsedTime(0.f);
|
||||
testGame->OnUserUpdate(0.f);
|
||||
REQUIRE(player->GetAbility3().GetCooldownTime()==player->GetAbility3().cooldown);
|
||||
}
|
||||
TEST(PlayerTests,"PlayerGetShieldCheck"){
|
||||
player=testGame->GetPlayer();
|
||||
REQUIRE(0U==player->GetShield());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerAddShieldCheck"){
|
||||
player=testGame->GetPlayer();
|
||||
player->AddShield(60U,5.f,PlayerTimerType::ADVANCE_SHIELD_TIMER);
|
||||
REQUIRE(60U==player->GetShield());
|
||||
testGame->SetElapsedTime(5.f);
|
||||
testGame->OnUserUpdate(5.f);
|
||||
REQUIRE(0U==player->GetShield());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerMultiShieldCheck"){
|
||||
player=testGame->GetPlayer();
|
||||
player->AddShield(60U,5.f,PlayerTimerType::ADVANCE_SHIELD_TIMER);
|
||||
player->AddShield(100U,2.f,PlayerTimerType::PLAYER_OUTLINE_TIMER);
|
||||
REQUIRE(160U==player->GetShield());
|
||||
testGame->SetElapsedTime(2.f);
|
||||
testGame->OnUserUpdate(2.f);
|
||||
REQUIRE(60U==player->GetShield());
|
||||
testGame->SetElapsedTime(3.f);
|
||||
testGame->OnUserUpdate(3.f);
|
||||
REQUIRE(0U==player->GetShield());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerSubtractShieldCheck"){
|
||||
player=testGame->GetPlayer();
|
||||
player->AddShield(60U,5.f,PlayerTimerType::ADVANCE_SHIELD_TIMER);
|
||||
REQUIRE(60U==player->GetShield());
|
||||
player->SubtractShield(40U);
|
||||
REQUIRE(20U==player->GetShield());
|
||||
player->SubtractShield(200U);
|
||||
REQUIRE(0U==player->GetShield());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerDamageShieldCheck"){
|
||||
player=testGame->GetPlayer();
|
||||
player->AddShield(60U,5.f,PlayerTimerType::ADVANCE_SHIELD_TIMER);
|
||||
REQUIRE(60U==player->GetShield());
|
||||
player->Hurt(20U,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(40U==player->GetShield());
|
||||
REQUIRE(player->GetMaxHealth()==player->GetHealth());
|
||||
player->Hurt(200U,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(0U==player->GetShield());
|
||||
REQUIRE(player->GetMaxHealth()==player->GetHealth());
|
||||
player->Hurt(10U,player->OnUpperLevel(),player->GetZ());
|
||||
REQUIRE(player->GetMaxHealth()-10==player->GetHealth());
|
||||
}
|
||||
TEST(PlayerTests,"PlayerHasteMoveCheck"){
|
||||
Game::LoadLevelWithTMX("TEST_MAP",testGame.get());
|
||||
player=testGame->GetPlayer();
|
||||
player->ForceSetPos({12,12});
|
||||
testKeyboardInput.AddKeybind(Input{InputType::KEY,D});
|
||||
testKey=testGame->GetKeyboardState(D);
|
||||
testKey->bHeld=true;
|
||||
{
|
||||
const vf2d originalPlayerPos{player->GetPos()};
|
||||
Game::Update(0.5f);
|
||||
REQUIRE(originalPlayerPos!=player->GetPos());
|
||||
const float movedDist{(originalPlayerPos-player->GetPos()).mag()};
|
||||
REQUIRE(50.f==movedDist);
|
||||
}
|
||||
Game::AddBuffToPlayer(BuffType::HASTEN,INFINITE,0.3f);
|
||||
const vf2d originalHastenedPlayerPos{player->GetPos()};
|
||||
Game::Update(0.5f);
|
||||
const float hastenMovedDist{(originalHastenedPlayerPos-player->GetPos()).mag()};
|
||||
REQUIRE(65.f==hastenMovedDist);
|
||||
player->RemoveAllBuffs();
|
||||
{
|
||||
const vf2d originalPlayerPos{player->GetPos()};
|
||||
Game::Update(0.5f);
|
||||
const float movedDist{(originalPlayerPos-player->GetPos()).mag()};
|
||||
REQUIRE(50.f==movedDist);
|
||||
}
|
||||
}
|
||||
TEST(PlayerTests,"PlayerHasteCooldownCheck"){
|
||||
Game::LoadLevelWithTMX("TEST_MAP",testGame.get());
|
||||
player=testGame->GetPlayer();
|
||||
player->ForceSetPos({12,12});
|
||||
testKeyboardInput.AddKeybind(Input{InputType::KEY,D});
|
||||
testKey=testGame->GetKeyboardState(D);
|
||||
testKey->bHeld=true;
|
||||
Game::CastAbilityAtLocation(player->GetAbility3(),{});
|
||||
Game::Update(5.f);
|
||||
REQUIRE(player->GetAbility3().GetCooldownTime()-5.f==player->GetAbility3().cooldown);
|
||||
Game::ResetPlayerAndChangeClass(Class::WARRIOR,player,&*testGame);
|
||||
Game::CastAbilityAtLocation(player->GetAbility3(),{});
|
||||
Game::AddBuffToPlayer(BuffType::HASTEN,INFINITE,0.3f);
|
||||
Game::Update(5.f);
|
||||
REQUIRE(player->GetAbility3().GetCooldownTime()-6.5f==player->GetAbility3().cooldown);
|
||||
player->RemoveAllBuffs();
|
||||
player->GetAbility3().cooldown=0;
|
||||
Game::CastAbilityAtLocation(player->GetAbility3(),{});
|
||||
Game::Update(5.f);
|
||||
REQUIRE(player->GetAbility3().GetCooldownTime()-5.f==player->GetAbility3().cooldown);
|
||||
}
|
||||
@ -7,4 +7,6 @@
|
||||
}
|
||||
$_
|
||||
} |
|
||||
Out-File $args[0] -encoding ascii -nonewline
|
||||
Out-File $args[0] -encoding ascii -nonewline
|
||||
|
||||
mv *Tests.cpp tests/
|
||||
@ -247,12 +247,12 @@ const std::string util::toLower(const std::string oldStr){
|
||||
|
||||
const std::string util::GetCaseInsensitiveFilename(const std::string&filename){
|
||||
if(std::filesystem::exists(filename))return filename;
|
||||
if(!std::filesystem::path{filename}.has_parent_path())ERR("WARNING! Invalid path {} for filename {}! THIS SHOULD NOT BE HAPPENING!");
|
||||
if(!std::filesystem::path{filename}.has_parent_path())ERR(std::format("WARNING! Invalid path {} for filename {}! THIS SHOULD NOT BE HAPPENING!",std::filesystem::path{filename}.string(),filename));
|
||||
for(auto&path:std::filesystem::recursive_directory_iterator(std::filesystem::path{filename}.parent_path())){
|
||||
if(path.is_regular_file()&&util::toLower(path.path().filename().string())==util::toLower(std::filesystem::path{filename}.filename().string())){
|
||||
return path.path().string();
|
||||
}
|
||||
}
|
||||
ERR("WARNING! Could not find or match case for filename {}! THIS SHOULD NOT BE HAPPENING!");
|
||||
ERR(std::format("WARNING! Could not find or match case for filename {}! THIS SHOULD NOT BE HAPPENING!",filename));
|
||||
std::unreachable();
|
||||
}
|
||||
@ -91,7 +91,7 @@ file(
|
||||
GLOB SOURCE_CXX_FILES
|
||||
"${SOURCE_CXX_SRC_DIR}/*.cpp"
|
||||
)
|
||||
if (NOT EMSCRIPTEN)
|
||||
if (NOT EMSCRIPTEN AND NOT TEST_ONLY)
|
||||
file(
|
||||
GLOB SOURCE_CXX_FILES2
|
||||
"${SOURCE_CXX_SRC_DIR}/discord-files/*.cpp"
|
||||
@ -100,37 +100,26 @@ endif()
|
||||
|
||||
list(APPEND SOURCE_CXX_FILES ${SOURCE_CXX_FILES2})
|
||||
|
||||
if(TEST_ONLY)
|
||||
file(
|
||||
GLOB SOURCE_CXX_TEST_FILES
|
||||
"${SOURCE_CXX_SRC_DIR}/tests/*.cpp"
|
||||
)
|
||||
list(APPEND SOURCE_CXX_FILES ${SOURCE_CXX_TEST_FILES})
|
||||
else()
|
||||
list(FILTER SOURCE_CXX_FILES EXCLUDE REGEX ".*Tests.cpp")
|
||||
endif()
|
||||
|
||||
# Search in the "cmake" directory for additional CMake modules.
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
if(NOT TEST_ONLY)
|
||||
# Executable aka binary output
|
||||
# Executable aka binary output
|
||||
if(TEST_ONLY)
|
||||
add_executable(AiL_test ${SOURCE_CXX_FILES})
|
||||
else()
|
||||
add_executable("${OutputExecutable}" ${SOURCE_CXX_FILES})
|
||||
endif()
|
||||
|
||||
|
||||
if(TEST_ONLY)
|
||||
set(SOURCE_CXX_TEST_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Adventures in Lestoria GTest")
|
||||
|
||||
# Source Files are Curated Here
|
||||
file(
|
||||
GLOB SOURCE_CXX_TEST_FILES
|
||||
"${SOURCE_CXX_TEST_SRC_DIR}/*.cpp"
|
||||
)
|
||||
|
||||
add_executable(AiL_test ${SOURCE_CXX_TEST_FILES})
|
||||
endif()
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
|
||||
)
|
||||
# For Windows: Prevent overriding the parent project's compiler/linker settings
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
|
||||
######################################################################
|
||||
# MacOS
|
||||
######################################################################
|
||||
@ -304,27 +293,6 @@ if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN AND NOT TEST_ONLY)
|
||||
-static-libstdc++
|
||||
"Adventures in Lestoria/discord_game_sdk.so"
|
||||
"Adventures in Lestoria/libsteam_api.so")
|
||||
|
||||
|
||||
enable_testing()
|
||||
|
||||
set(SOURCE_CXX_TEST_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Adventures in Lestoria GTest")
|
||||
|
||||
# Source Files are Curated Here
|
||||
file(
|
||||
GLOB SOURCE_CXX_TEST_FILES
|
||||
"${SOURCE_CXX_TEST_SRC_DIR}/*.cpp"
|
||||
)
|
||||
|
||||
add_executable(AiL_test ${SOURCE_CXX_TEST_FILES})
|
||||
target_link_libraries(
|
||||
AiL_test
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(AiL_test)
|
||||
|
||||
endif() # Linux
|
||||
|
||||
if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN AND TEST_ONLY)
|
||||
@ -332,12 +300,12 @@ if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN AND TEST_ONLY)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(AiL_test Threads::Threads)
|
||||
include_directories(${Threads_INCLUDE_DIRS})
|
||||
target_link_libraries(AiL_test -lstdc++exp)
|
||||
|
||||
find_package(Freetype REQUIRED)
|
||||
target_link_libraries(AiL_test ${FREETYPE_LIBRARIES})
|
||||
target_include_directories(AiL_test PRIVATE ${FREETYPE_INCLUDE_DIRS})
|
||||
|
||||
target_include_directories(AiL_test PRIVATE "${C_CXX_SOURCES_DIR}/discord-files")
|
||||
target_include_directories(AiL_test PRIVATE "${C_CXX_SOURCES_DIR}/steam")
|
||||
link_directories("Adventures in Lestoria")
|
||||
|
||||
@ -346,7 +314,8 @@ if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN AND TEST_ONLY)
|
||||
include_directories(${PNG_INCLUDE_DIRS})
|
||||
|
||||
# stdc++fs
|
||||
target_link_libraries(AiL_test stdc++fs)
|
||||
target_link_libraries(AiL_test stdc++fs)
|
||||
target_link_libraries(AiL_test stdc++exp)
|
||||
link_directories("${CMAKE_SOURCE_DIR}/Adventures in Lestoria")
|
||||
add_library( discord_game_sdk SHARED IMPORTED )
|
||||
set_property(TARGET discord_game_sdk PROPERTY IMPORTED_LOCATION "Adventures in Lestoria/discord_game_sdk.so")
|
||||
@ -358,6 +327,7 @@ if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN AND TEST_ONLY)
|
||||
target_link_libraries(AiL_test dl)
|
||||
|
||||
add_compile_definitions(OLC_PGE_HEADLESS)
|
||||
add_compile_definitions(UNIT_TESTING)
|
||||
|
||||
target_link_options(
|
||||
AiL_test
|
||||
@ -366,17 +336,6 @@ if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN AND TEST_ONLY)
|
||||
"Adventures in Lestoria/discord_game_sdk.so"
|
||||
"Adventures in Lestoria/libsteam_api.so")
|
||||
|
||||
|
||||
enable_testing()
|
||||
|
||||
target_link_libraries(
|
||||
AiL_test
|
||||
GTest::gtest_main
|
||||
)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(AiL_test)
|
||||
|
||||
endif() # Linux
|
||||
|
||||
|
||||
|
||||
2
git-hooks/Windows/post-commit
Normal file
2
git-hooks/Windows/post-commit
Normal file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
powershell.exe -ExecutionPolicy RemoteSigned -File '.git\hooks\post-commit.ps1'
|
||||
4
git-hooks/Windows/post-commit.ps1
Normal file
4
git-hooks/Windows/post-commit.ps1
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
Compress-Archive -Path "J:\AdventuresInLestoria\x64\Unit Testing\assets" -Force -DestinationPath "J:\AdventuresInLestoria\x64\Unit Testing\assets.zip"
|
||||
pscp -r -pwfile "C:\Users\sigon\OneDrive\Documents\pw.DONOTOPEN" "J:\AdventuresInLestoria\x64\Unit Testing\assets.zip" sigonasr2@projectdivar.com:/home/sigonasr2
|
||||
rm "J:\AdventuresInLestoria\x64\Unit Testing\assets.zip"
|
||||
@ -1,5 +1,5 @@
|
||||
cd "bin"
|
||||
cp "../Adventures in Lestoria/discord_game_sdk.so" .
|
||||
cp "../Adventures in Lestoria/libsteam_api.so" .
|
||||
cd ..
|
||||
ctest --output-on-failure
|
||||
mkdir "Adventures in Lestoria"
|
||||
cp "../Adventures in Lestoria/discord_game_sdk.so" "./Adventures in Lestoria"
|
||||
cp "../Adventures in Lestoria/libsteam_api.so" "./Adventures in Lestoria"
|
||||
./AiL_test -d yes --use-colour yes
|
||||
2
test.sh
2
test.sh
@ -1,3 +1,5 @@
|
||||
rm CMakeCache.txt
|
||||
cp "./Adventures in Lestoria/discord_game_sdk.so" .
|
||||
cp "./Adventures in Lestoria/libsteam_api.so" .
|
||||
git update-index --assume-unchanged "Adventures in Lestoria/packkey.cpp"
|
||||
cmake -DTEST_ONLY=ON -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_BUILD_TYPE=Release .;make -j 8
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user