Compare commits
29 Commits
3602de5c3b
...
25c196a563
Author | SHA1 | Date | |
---|---|---|---|
25c196a563 | |||
f962e90cad | |||
2fea77c66c | |||
38d72e24a1 | |||
67ca0d168d | |||
bee8d6d306 | |||
08ec6b7ed4 | |||
fab7f34afa | |||
ae6e5af5f6 | |||
b9994242dd | |||
b43e6e5bf1 | |||
cb3f38e07c | |||
93298e05d3 | |||
62ef4d2815 | |||
1d1cb7170c | |||
8c8567017c | |||
2447a6bbb1 | |||
dcb31a01e1 | |||
9722695e5b | |||
7308a7e37b | |||
0f012faf36 | |||
8d8534c90b | |||
5a4e7fb53b | |||
1dd3e31735 | |||
97820bf52b | |||
a6e121cbaa | |||
c91130eded | |||
6da5e5b98b | |||
1fe27dce95 |
@ -47,7 +47,7 @@
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unit Testing|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<IncludePath>$(ProjectDir)..\AdventuresInLestoria\Adventures in Lestoria;$(ProjectDir)..\AdventuresInLestoria\Adventures in Lestoria\include;$(IncludePath)</IncludePath>
|
||||
<IncludePath>C:\Users\LabUser\source\repos\AdventuresInLestoria\Adventures in Lestoria\include;C:\Users\LabUser\source\repos\AdventuresInLestoria\Adventures in Lestoria;$(SolutionDir)Adventures in Lestoria;$(SolutionDir)Adventures in Lestoria\include$(SolutionDir);$(IncludePath)</IncludePath>
|
||||
<OutDir>..\x64\Unit Testing</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Unit Testing|Win32'">
|
||||
@ -58,7 +58,7 @@
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>J:\AdventuresInLestoria\Adventures in Lestoria\steam;J:\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\niconiconii\source\repos\AdventuresInLestoria\Adventures in Lestoria\steam;C:\Users\sigon\source\repos\AdventuresInLestoria\Adventures in Lestoria\steam;C:\Users\niconiconii\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\sigon\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\niconiconii\OneDrive\Documents\include;C:\Users\sigon\OneDrive\Documents\include;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>C:\Users\LabUser\source\repos\AdventuresInLestoria\Adventures in Lestoria\include;J:\AdventuresInLestoria\Adventures in Lestoria\steam;J:\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\niconiconii\source\repos\AdventuresInLestoria\Adventures in Lestoria\steam;C:\Users\LabUser\source\repos\AdventuresInLestoria\Adventures in Lestoria\steam;C:\Users\sigon\source\repos\AdventuresInLestoria\Adventures in Lestoria\steam;C:\Users\niconiconii\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\LabUser\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\sigon\source\repos\AdventuresInLestoria\Adventures in Lestoria\discord-files;C:\Users\niconiconii\OneDrive\Documents\include;C:\Users\LabUser\OneDrive\Documents\include;C:\Users\sigon\OneDrive\Documents\include;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<UseFullPaths>true</UseFullPaths>
|
||||
<PrecompiledHeaderFile>
|
||||
|
@ -113,6 +113,49 @@ namespace EnchantTests
|
||||
testGame->OnUserUpdate(0.f);
|
||||
testGame.reset();
|
||||
}
|
||||
TEST_METHOD(AbilityNameWithPlayerModifiersWorks){
|
||||
Game::ChangeClass(player,RANGER);
|
||||
Assert::AreEqual("Rapid Fire",player->GetAbility1().GetNameWithPlayerModifiers().c_str(),L"Ability name should be unmodified with no modifiers applied.");
|
||||
Assert::AreEqual("Shoots #45F9FFfour#FFFFFF arrows rapidly. Total Damage: #45F9FF52#FFFFFF.",player->GetAbility1().GetDescriptionWithPlayerModifiers().c_str(),L"Ability descriptions should be unmodified with no modifiers applied.");
|
||||
|
||||
Game::GiveAndEquipEnchantedRing("Extreme Rapid Fire");
|
||||
Assert::AreEqual("Extreme Rapid Fire",player->GetAbility1().GetNameWithPlayerModifiers().c_str(),L"Ability name should be modified with appropriate modifier applied.");
|
||||
Assert::AreEqual("Shoots #45F9FFnine#FFFFFF arrows rapidly. Total Damage: #45F9FF117#FFFFFF.",player->GetAbility1().GetDescriptionWithPlayerModifiers().c_str(),L"Ability description should be modified with appropriate modifier applied.");
|
||||
|
||||
Inventory::UnequipItem(EquipSlot::RING1);
|
||||
Assert::AreEqual("Rapid Fire",player->GetAbility1().GetNameWithPlayerModifiers().c_str(),L"After unequipping Ability name should be back to normal with no modifiers applied.");
|
||||
Assert::AreEqual("Shoots #45F9FFfour#FFFFFF arrows rapidly. Total Damage: #45F9FF52#FFFFFF.",player->GetAbility1().GetDescriptionWithPlayerModifiers().c_str(),L"After unequipping Ability descriptions should be back to normal with no modifiers applied.");
|
||||
}
|
||||
TEST_METHOD(AbilityDescriptionModifiersPopulateProperly){
|
||||
ItemEnchantInfo::AbilityDescriptionModifiers modifiers{"Test Enchant"_ENC.GetModifiers()};
|
||||
Assert::AreEqual("Test",(*modifiers.preName).c_str(),L"Pre-name reads in properly");
|
||||
Assert::AreEqual("Enchant",(*modifiers.newName).c_str(),L"Replacement name reads in properly");
|
||||
Assert::IsFalse(modifiers.postName.has_value(),L"Post-name should not have a value.");
|
||||
Assert::AreEqual("Pre test",(*modifiers.preDescription).c_str(),L"Pre-description reads in properly");
|
||||
Assert::AreEqual("My Description",(*modifiers.newDescription).c_str(),L"Replacement description reads in properly");
|
||||
Assert::AreEqual("Post test",(*modifiers.postDescription).c_str(),L"Post-description reads in properly");
|
||||
}
|
||||
TEST_METHOD(AllEnchantsAffectingAbilityTest){
|
||||
for(int classBits{int(Class::WARRIOR)};classBits<=int(Class::WITCH);classBits<<=1){
|
||||
const Class cl{Class(classBits)};
|
||||
Game::ChangeClass(player,cl);
|
||||
for(const Ability&ability:player->GetAbilities()){
|
||||
Assert::AreEqual(size_t(0),ItemEnchantInfo::GetAllEnchantsAffectingAbility(ability.GetName()).size(),util::wformat("There should be no enchants affecting ability {} by default.",ability.GetName()).c_str());
|
||||
}
|
||||
}
|
||||
Game::GiveAndEquipEnchantedRing("Heavy Guard");
|
||||
Assert::AreEqual(size_t(1),ItemEnchantInfo::GetAllEnchantsAffectingAbility("Block").size(),L"There should be 1 enchant affecting ability Block.");
|
||||
Game::GiveAndEquipEnchantedRing("Advance Shield",EquipSlot::RING2);
|
||||
Assert::AreEqual(size_t(2),ItemEnchantInfo::GetAllEnchantsAffectingAbility("Block").size(),L"There should be 2 enchants affecting ability Block.");
|
||||
Inventory::UnequipItem(EquipSlot::RING1);
|
||||
Assert::AreEqual(size_t(1),ItemEnchantInfo::GetAllEnchantsAffectingAbility("Block").size(),L"There should be 1 enchant affecting ability Block.");
|
||||
Game::GiveAndEquipEnchantedRing("Advance Shield");
|
||||
Assert::AreEqual(size_t(1),ItemEnchantInfo::GetAllEnchantsAffectingAbility("Block").size(),L"With two of the same enchant, there should only be 1 enchant enchants affecting ability Block.");
|
||||
Inventory::UnequipItem(EquipSlot::RING2);
|
||||
Assert::AreEqual(size_t(1),ItemEnchantInfo::GetAllEnchantsAffectingAbility("Block").size(),L"There should be 1 enchant affecting ability Block.");
|
||||
Inventory::UnequipItem(EquipSlot::RING1);
|
||||
Assert::AreEqual(size_t(0),ItemEnchantInfo::GetAllEnchantsAffectingAbility("Block").size(),L"There should be no enchants affecting ability Block by default.");
|
||||
}
|
||||
TEST_METHOD(HealthBoostCheck){
|
||||
Assert::AreEqual(100,player->GetMaxHealth(),L"Player starts with 100 health.");
|
||||
std::weak_ptr<Item>nullRing{Game::GiveAndEquipEnchantedRing("Aura of the Beast")};
|
||||
|
@ -174,5 +174,21 @@ namespace EngineTests
|
||||
Assert::AreEqual(200.f,util::map_range<float>(100.f,50,100,100,200),L"100 in input range 50-100 output range 100-200 maps to 200");
|
||||
Assert::AreEqual(100.f,util::map_range<float>(50.f,50,100,100,200),L"50 in input range 50-100 output range 100-200 maps to 100");
|
||||
}
|
||||
|
||||
TEST_METHOD(ClassUtilTest){
|
||||
Assert::AreEqual(int(Class::WARRIOR),int(classutils::StringToClass("Warrior")),L"Expected Warrior to return the warrior class.");
|
||||
Assert::AreEqual(int(Class::WIZARD),int(classutils::StringToClass("Wizard")),L"Expected Wizard to return the wizard class.");
|
||||
Assert::AreEqual(int(Class::RANGER),int(classutils::StringToClass("Ranger")),L"Expected Ranger to return the ranger class.");
|
||||
Assert::AreEqual(int(Class::THIEF),int(classutils::StringToClass("Thief")),L"Expected Thief to return the thief class.");
|
||||
Assert::AreEqual(int(Class::WITCH),int(classutils::StringToClass("Witch")),L"Expected Witch to return the witch class.");
|
||||
Assert::AreEqual(int(Class::TRAPPER),int(classutils::StringToClass("Trapper")),L"Expected Trapper to return the trapper class.");
|
||||
|
||||
Assert::AreEqual("Warrior",classutils::ClassToString(Class::WARRIOR).c_str(),L"Expected class to string to convert properly");
|
||||
Assert::AreEqual("Wizard",classutils::ClassToString(Class::WIZARD).c_str(),L"Expected class to string to convert properly");
|
||||
Assert::AreEqual("Ranger",classutils::ClassToString(Class::RANGER).c_str(),L"Expected class to string to convert properly");
|
||||
Assert::AreEqual("Thief",classutils::ClassToString(Class::THIEF).c_str(),L"Expected class to string to convert properly");
|
||||
Assert::AreEqual("Witch",classutils::ClassToString(Class::WITCH).c_str(),L"Expected class to string to convert properly");
|
||||
Assert::AreEqual("Trapper",classutils::ClassToString(Class::TRAPPER).c_str(),L"Expected class to string to convert properly");
|
||||
}
|
||||
};
|
||||
}
|
BIN
Adventures in Lestoria Tests/discord_game_sdk.dll.lib
Normal file
BIN
Adventures in Lestoria Tests/discord_game_sdk.dll.lib
Normal file
Binary file not shown.
BIN
Adventures in Lestoria Tests/freetype.lib
Normal file
BIN
Adventures in Lestoria Tests/freetype.lib
Normal file
Binary file not shown.
BIN
Adventures in Lestoria Tests/steam_api64.lib
Normal file
BIN
Adventures in Lestoria Tests/steam_api64.lib
Normal file
Binary file not shown.
@ -68,10 +68,148 @@ const bool Ability::operator==(const Ability&a)const{
|
||||
return name==a.name&&isOriginalAbility==a.isOriginalAbility;
|
||||
}
|
||||
|
||||
const std::string Ability::GetName()const{
|
||||
return std::format("{}",name);
|
||||
const std::string&Ability::GetName()const{
|
||||
return name;
|
||||
}
|
||||
|
||||
const std::string_view Ability::GetDescription()const{
|
||||
return description;
|
||||
}
|
||||
|
||||
const std::string Ability::GetNameWithPlayerModifiers()const{
|
||||
std::string prefixName{};
|
||||
std::string newName{name};
|
||||
std::string suffixName{};
|
||||
for(const auto&enchant:ItemEnchantInfo::GetAllEnchantsAffectingAbility(name)){
|
||||
const ItemEnchantInfo::AbilityDescriptionModifiers&modifiers{enchant.get().GetModifiers()};
|
||||
if(prefixName.length()>0&&modifiers.preName)prefixName+=" ";
|
||||
prefixName+=modifiers.preName.value_or("");
|
||||
if(modifiers.newName)newName=modifiers.newName.value();
|
||||
if(suffixName.length()>0&&modifiers.preName)suffixName+=" ";
|
||||
suffixName+=modifiers.postName.value_or("");
|
||||
}
|
||||
std::string finalName{prefixName};
|
||||
if(finalName.length()>0&&newName.length()>0)finalName+=' ';
|
||||
finalName+=newName;
|
||||
if(finalName.length()>0&&suffixName.length()>0)finalName+=' ';
|
||||
finalName+=suffixName;
|
||||
return finalName;
|
||||
}
|
||||
|
||||
const std::string Ability::GetDescriptionWithPlayerModifiers()const{
|
||||
using SpecialKey=std::string;
|
||||
using TranslateFunc=std::function<std::string(const datafile&data,const std::string&val)>;
|
||||
std::unordered_map<SpecialKey,TranslateFunc>specialPrefixes{
|
||||
#define TranslateFunc [&](const datafile&data,const std::string&val)->std::string
|
||||
{"DamageMult",TranslateFunc{
|
||||
float damageMult{stof(data.at(val).GetString())};
|
||||
int finalDmg{int(damageMult*game->GetPlayer()->GetAttack())};
|
||||
return std::format("{}",finalDmg);
|
||||
}},
|
||||
};
|
||||
const Pixel specialValCol{69,249,255};
|
||||
|
||||
const auto ParseVariables=[&](const std::string_view abilityText)->std::string{
|
||||
std::string finalText{};
|
||||
size_t marker{};
|
||||
std::string variableName{};
|
||||
bool bracesFound{false};
|
||||
|
||||
const auto FindAndParse=[&finalText,&bracesFound,&variableName,&specialPrefixes,&specialValCol](datafile&data)->bool{
|
||||
if(data.HasProperty(variableName)){
|
||||
finalText+=specialValCol.toHTMLColorCode()+data.GetProperty(variableName).GetFullString()+WHITE.toHTMLColorCode();
|
||||
bracesFound=false;
|
||||
variableName="";
|
||||
return true;
|
||||
}else if(size_t separatorMarker{std::string::npos};(separatorMarker=variableName.find(':'))!=std::string::npos){
|
||||
std::string separatorKey{variableName.substr(0,separatorMarker)};
|
||||
std::string separatorVal{variableName.substr(separatorMarker+1)};
|
||||
if(!specialPrefixes.count(separatorKey))ERR(std::format("Could not find translation function for key {} inside special prefixes map!",separatorKey))
|
||||
else {
|
||||
finalText+=specialValCol.toHTMLColorCode()+specialPrefixes[separatorKey](data,separatorVal)+WHITE.toHTMLColorCode();
|
||||
bracesFound=false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
while(marker<abilityText.length()){
|
||||
const char c{abilityText[marker]};
|
||||
if(!bracesFound&&c=='{')bracesFound=true;
|
||||
else if(bracesFound&&c=='}'){ //Parse the variable.
|
||||
if(!FindAndParse((*abilityConfig).get()))
|
||||
ERR(std::format("Could not find variable {} for Ability {}",variableName,GetName()));
|
||||
}else if(bracesFound)variableName+=c;
|
||||
else finalText+=c;
|
||||
marker++;
|
||||
}
|
||||
return finalText;
|
||||
};
|
||||
|
||||
std::string prefixDescription{};
|
||||
std::string newDescription{ParseVariables(description)};
|
||||
std::string suffixDescription{};
|
||||
bool descriptionHasBeenModifiedAgain{false};
|
||||
for(const auto&enchant:ItemEnchantInfo::GetAllEnchantsAffectingAbility(name)){
|
||||
const ItemEnchantInfo::AbilityDescriptionModifiers&modifiers{enchant.get().GetModifiers()};
|
||||
if(prefixDescription.length()>0&&modifiers.preDescription)prefixDescription+=" ";
|
||||
prefixDescription+=modifiers.preDescription.value_or("");
|
||||
if(modifiers.newDescription)newDescription=*modifiers.newDescription;
|
||||
if(suffixDescription.length()>0&&modifiers.preDescription)suffixDescription+=" ";
|
||||
suffixDescription+=modifiers.postDescription.value_or("");
|
||||
|
||||
const auto ParseVariablesForEnchant=[&](const std::string_view abilityText)->std::string{
|
||||
std::string finalText{};
|
||||
size_t marker{};
|
||||
std::string variableName{};
|
||||
bool bracesFound{false};
|
||||
|
||||
const auto FindAndParse=[&finalText,&bracesFound,&variableName,&specialPrefixes,&specialValCol](datafile&data)->bool{
|
||||
if(data.HasProperty(variableName)){
|
||||
finalText+=specialValCol.toHTMLColorCode()+data.GetProperty(variableName).GetFullString()+WHITE.toHTMLColorCode();
|
||||
bracesFound=false;
|
||||
variableName="";
|
||||
return true;
|
||||
}else if(size_t separatorMarker{std::string::npos};(separatorMarker=variableName.find(':'))!=std::string::npos){
|
||||
std::string separatorKey{variableName.substr(0,separatorMarker)};
|
||||
std::string separatorVal{variableName.substr(separatorMarker+1)};
|
||||
if(!specialPrefixes.count(separatorKey))ERR(std::format("Could not find translation function for key {} inside special prefixes map!",separatorKey))
|
||||
else {
|
||||
finalText+=specialValCol.toHTMLColorCode()+specialPrefixes[separatorKey](data,separatorVal)+WHITE.toHTMLColorCode();
|
||||
bracesFound=false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
while(marker<abilityText.length()){
|
||||
const char c{abilityText[marker]};
|
||||
if(!bracesFound&&c=='{')bracesFound=true;
|
||||
else if(bracesFound&&c=='}'){ //Parse the variable.
|
||||
if(!FindAndParse(enchant.get().GetData()["Ability Settings"]))
|
||||
if(!FindAndParse(enchant.get().GetData()))
|
||||
if(!FindAndParse((*(*enchant.get().GetAbility())->abilityConfig).get()))
|
||||
ERR(std::format("Could not find variable {} for enchant Ability Settings of enchantment {}",variableName,enchant.get().Name()));
|
||||
}else if(bracesFound)variableName+=c;
|
||||
else finalText+=c;
|
||||
marker++;
|
||||
}
|
||||
return finalText;
|
||||
};
|
||||
prefixDescription=ParseVariablesForEnchant(prefixDescription);
|
||||
if(!descriptionHasBeenModifiedAgain){
|
||||
descriptionHasBeenModifiedAgain=true;
|
||||
newDescription=description;
|
||||
}
|
||||
newDescription=ParseVariablesForEnchant(newDescription);
|
||||
suffixDescription=ParseVariablesForEnchant(suffixDescription);
|
||||
}
|
||||
std::string finalDescription{prefixDescription};
|
||||
if(finalDescription.length()>0&&newDescription.length()>0)finalDescription+=' ';
|
||||
finalDescription+=newDescription;
|
||||
if(finalDescription.length()>0&&suffixDescription.length()>0)finalDescription+=' ';
|
||||
finalDescription+=suffixDescription;
|
||||
return finalDescription;
|
||||
}
|
@ -37,8 +37,8 @@ All rights reserved.
|
||||
#pragma endregion
|
||||
#pragma once
|
||||
#include "Key.h"
|
||||
#include "olcPixelGameEngine.h"
|
||||
#include <string_view>
|
||||
#include "olcUTIL_DataFile.h"
|
||||
|
||||
class InputGroup;
|
||||
|
||||
@ -90,10 +90,14 @@ struct Ability{
|
||||
static std::string tooltipText;
|
||||
static std::string tooltipTitle;
|
||||
static Pixel tooltipTitleCol;
|
||||
std::optional<std::reference_wrapper<datafile>>abilityConfig;
|
||||
constexpr static float MAX_DESCRIPTION_HOVER_TIME{0.3f};
|
||||
Ability();
|
||||
//NOTE: icon expects the actual name relative to the "Ability Icons" directory for this constructor!
|
||||
Ability(std::string name,std::string shortName,std::string description,float cooldownTime,int manaCost,InputGroup*input,std::string icon,Pixel barColor1=VERY_DARK_RED,Pixel barColor2=DARK_RED,PrecastData precastInfo={},bool canCancelCast=false);
|
||||
const std::string GetName()const;
|
||||
const std::string&GetName()const;
|
||||
const std::string_view GetDescription()const;
|
||||
|
||||
const std::string GetNameWithPlayerModifiers()const;
|
||||
const std::string GetDescriptionWithPlayerModifiers()const;
|
||||
};
|
@ -1314,6 +1314,12 @@
|
||||
<None Include="steam\steam_api.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<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" />
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\ItemEnchants-test.txt" />
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\items-test.txt" />
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\ItemSets-test.txt" />
|
||||
<Text Include="..\x64\Unit Testing\debug.log" />
|
||||
<Text Include="assets\config\Achievements.txt" />
|
||||
<Text Include="assets\config\audio\audio.txt" />
|
||||
|
@ -106,6 +106,9 @@
|
||||
<Filter Include="Debug">
|
||||
<UniqueIdentifier>{c4119802-3fc8-4555-9013-a7a3ac9b204d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Configurations\Items\Test Configurations">
|
||||
<UniqueIdentifier>{354b389b-2ec1-4cf6-ace0-6597b14edfab}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="olcPixelGameEngine.h">
|
||||
@ -711,12 +714,12 @@
|
||||
<ClInclude Include="Arc.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Entity.h">
|
||||
<Filter>Header Files\Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="State_Arena.h">
|
||||
<Filter>Header Files\State</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Entity.h">
|
||||
<Filter>Header Files\State</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Player.cpp">
|
||||
@ -1583,6 +1586,24 @@
|
||||
<Text Include="Chapter_3_FinalBoss.txt">
|
||||
<Filter>Documentation\Mechanics</Filter>
|
||||
</Text>
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\Accessories-test.txt">
|
||||
<Filter>Configurations\Items\Test Configurations</Filter>
|
||||
</Text>
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\Equipment-test.txt">
|
||||
<Filter>Configurations\Items\Test Configurations</Filter>
|
||||
</Text>
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\ItemDatabase-test.txt">
|
||||
<Filter>Configurations\Items\Test Configurations</Filter>
|
||||
</Text>
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\ItemEnchants-test.txt">
|
||||
<Filter>Configurations\Items\Test Configurations</Filter>
|
||||
</Text>
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\ItemSets-test.txt">
|
||||
<Filter>Configurations\Items\Test Configurations</Filter>
|
||||
</Text>
|
||||
<Text Include="..\x64\Unit Testing\assets\config\items\items-test.txt">
|
||||
<Filter>Configurations\Items\Test Configurations</Filter>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="assets\heart.ico">
|
||||
|
@ -179,7 +179,7 @@ AiL::AiL(bool testingMode){
|
||||
utils::datafile::Read(DATA,ITEM_SET_CONFIG,',',datafile::OverwriteMode::OVERWRITE);
|
||||
auto keys=DATA.GetProperty("ItemConfiguration");
|
||||
for(auto&[key,value]:keys){
|
||||
std::string config=DATA["ItemConfiguration"][key].GetString();
|
||||
std::string config=DATA["ItemConfiguration"][key].GetString();
|
||||
utils::datafile::Read(DATA,CONFIG_PATH + "item_directory"_S + config,',',datafile::OverwriteMode::OVERWRITE);
|
||||
}
|
||||
}
|
||||
@ -2183,8 +2183,8 @@ void AiL::RenderCooldowns(){
|
||||
if(HasEnchantWithAbilityAffected)abilityTitleCol=Pixel{0xFFCD00};
|
||||
if(a.itemAbility)abilityTitleCol=Pixel{0xA2FF00};
|
||||
Ability::tooltipTitleCol=abilityTitleCol;
|
||||
Ability::tooltipTitle=std::format("{}",a.GetName());
|
||||
Ability::tooltipText=std::format("{}",a.GetDescription());
|
||||
Ability::tooltipTitle=std::format("{}",a.GetNameWithPlayerModifiers());
|
||||
Ability::tooltipText=std::format("{}",a.GetDescriptionWithPlayerModifiers());
|
||||
}
|
||||
}else heldDownAnyAbilityKey=true;
|
||||
#pragma endregion
|
||||
@ -3011,6 +3011,11 @@ void AiL::InitializeClasses(){
|
||||
Trapper::CreateOriginalCopies();
|
||||
Wizard::CreateOriginalCopies();
|
||||
Witch::CreateOriginalCopies();
|
||||
|
||||
for(int classBitCount{0b1};const std::string&cl:DATA["class_list"].GetValues()){
|
||||
classutils::classList[Class(classBitCount)]=cl;
|
||||
classBitCount<<=1;
|
||||
}
|
||||
}
|
||||
|
||||
std::string AiL::GetString(std::string key){
|
||||
|
@ -56,6 +56,7 @@ enum Class{
|
||||
};
|
||||
|
||||
namespace classutils{//Classes have bit-wise operator capabilities.
|
||||
inline std::unordered_map<Class,std::string>classList;
|
||||
static inline Class StringToClass(std::string className){
|
||||
const std::vector<std::string>&classList=DATA["class_list"].GetValues();
|
||||
auto it=std::find(classList.begin(),classList.end(),className);
|
||||
@ -63,4 +64,7 @@ namespace classutils{//Classes have bit-wise operator capabilities.
|
||||
int element=int(std::distance(classList.begin(),it));
|
||||
return Class(1<<element); //Yes...It's bitwise flags, who in god's name knows why I did this.
|
||||
};
|
||||
static inline std::string ClassToString(const Class&cl){
|
||||
return classList.at(cl);
|
||||
}
|
||||
};
|
@ -117,7 +117,20 @@ void ItemEnchantInfo::Initialize(){
|
||||
newEnchant.abilitySlot=affectSlots.at(affectStr);
|
||||
}
|
||||
|
||||
auto IsRequiredKey=[](const std::string_view key){return key=="Description"||key=="Affects"||key.starts_with("Stat Modifier[");};
|
||||
ItemEnchantInfo::AbilityDescriptionModifiers modifiers;
|
||||
if(enchant.HasProperty("Ability Settings")){
|
||||
for(const auto&[key,size]:enchant["Ability Settings"]){
|
||||
|
||||
if(key=="Pre-Name")modifiers.preName=enchant["Ability Settings"][key].GetFullString();
|
||||
else if(key=="Post-Name")modifiers.postName=enchant["Ability Settings"][key].GetFullString();
|
||||
else if(key=="Name")modifiers.newName=enchant["Ability Settings"][key].GetFullString();
|
||||
else if(key=="Pre-Description")modifiers.preDescription=enchant["Ability Settings"][key].GetFullString();
|
||||
else if(key=="Post-Description")modifiers.postDescription=enchant["Ability Settings"][key].GetFullString();
|
||||
else if(key=="Description")modifiers.newDescription=enchant["Ability Settings"][key].GetFullString();
|
||||
}
|
||||
}
|
||||
|
||||
auto IsRequiredKey=[](const std::string_view key){return key=="Description"||key=="Affects"||key.starts_with("Stat Modifier[")||key.starts_with("Ability Settings");};
|
||||
|
||||
for(auto&[key,size]:enchant){
|
||||
if(IsRequiredKey(key))continue;
|
||||
@ -143,6 +156,7 @@ void ItemEnchantInfo::Initialize(){
|
||||
}
|
||||
|
||||
newEnchant.description=enchantDescription;
|
||||
newEnchant.modifiers=modifiers;
|
||||
|
||||
return newEnchant;
|
||||
};
|
||||
@ -181,7 +195,7 @@ ItemEnchant::ItemEnchant(const std::string_view enchantName)
|
||||
}
|
||||
}
|
||||
|
||||
const ItemEnchantInfo&ItemEnchantInfo::GetEnchant(const std::string_view enchantName){
|
||||
ItemEnchantInfo&ItemEnchantInfo::GetEnchant(const std::string_view enchantName){
|
||||
return ENCHANT_LIST.at(std::string(enchantName));
|
||||
}
|
||||
|
||||
@ -350,4 +364,30 @@ const bool ItemEnchant::HasAttributes()const{
|
||||
|
||||
const std::optional<Class>&ItemEnchant::GetClass()const{
|
||||
return ItemEnchantInfo::GetEnchant(Name()).GetClass();
|
||||
}
|
||||
const std::vector<std::reference_wrapper<ItemEnchantInfo>>ItemEnchantInfo::GetAllEnchantsAffectingAbility(const std::string_view ability){
|
||||
std::vector<std::reference_wrapper<ItemEnchantInfo>>enchantsAffectingList{};
|
||||
for(const auto&enchantName:game->GetPlayer()->GetEnchants()){
|
||||
ItemEnchantInfo&enchant{ItemEnchantInfo::GetEnchant(enchantName)};
|
||||
if(enchant.GetAbility()&&(*enchant.GetAbility())->GetName()==ability)enchantsAffectingList.emplace_back(std::ref(enchant));
|
||||
}
|
||||
return enchantsAffectingList;
|
||||
}
|
||||
const ItemEnchantInfo::AbilityDescriptionModifiers ItemEnchantInfo::GetModifiers()const{
|
||||
return modifiers;
|
||||
}
|
||||
datafile&ItemEnchantInfo::GetData(){
|
||||
switch(Category()){
|
||||
case ItemEnchantCategory::CLASS:{
|
||||
return DATA["Item Enchants"]["Class Enchants"][classutils::ClassToString(*GetClass())][Name()];
|
||||
}break;
|
||||
case ItemEnchantCategory::GENERAL:{
|
||||
return DATA["Item Enchants"]["General Enchants"];
|
||||
}break;
|
||||
case ItemEnchantCategory::UNIQUE:{
|
||||
return DATA["Item Enchants"]["Unique Enchants"];
|
||||
}break;
|
||||
}
|
||||
ERR(std::format("An undefined return path was reached for some reason while trying to retrieve data! Category: {}",int(Category())));
|
||||
return DATA;
|
||||
}
|
@ -64,10 +64,19 @@ public:
|
||||
ABILITY_3,
|
||||
};
|
||||
|
||||
struct AbilityDescriptionModifiers{
|
||||
std::optional<std::string>preName;
|
||||
std::optional<std::string>postName;
|
||||
std::optional<std::string>newName;
|
||||
std::optional<std::string>preDescription;
|
||||
std::optional<std::string>postDescription;
|
||||
std::optional<std::string>newDescription;
|
||||
};
|
||||
|
||||
const static Pixel enchantAttributeCol;
|
||||
|
||||
static void Initialize();
|
||||
const static ItemEnchantInfo&GetEnchant(const std::string_view enchantName);
|
||||
static ItemEnchantInfo&GetEnchant(const std::string_view enchantName);
|
||||
const static std::unordered_map<std::string,ItemEnchantInfo>&GetEnchants();
|
||||
static std::unordered_map<ItemEnchantCategory,Pixel>enchantTextDisplayCol;
|
||||
|
||||
@ -78,8 +87,11 @@ public:
|
||||
const std::optional<AbilitySlot>&GetAbilitySlot()const;
|
||||
const std::optional<Ability*>GetAbility()const; //Get the ability this enchant is tied to.
|
||||
const Pixel&DisplayCol()const;
|
||||
const float GetConfigValue(const std::string_view keyName)const;
|
||||
const float GetConfigValue(const std::string_view keyName)const;
|
||||
const float operator[](const std::string&name)const;
|
||||
const AbilityDescriptionModifiers GetModifiers()const;
|
||||
static const std::vector<std::reference_wrapper<ItemEnchantInfo>>GetAllEnchantsAffectingAbility(const std::string_view ability);
|
||||
datafile&GetData();
|
||||
private:
|
||||
class ItemEnchantCategoryData{
|
||||
friend class ItemEnchantInfo;
|
||||
@ -98,6 +110,7 @@ private:
|
||||
std::unordered_map<std::string,float>config;
|
||||
static std::unordered_map<std::string,ItemEnchantInfo>ENCHANT_LIST;
|
||||
static std::unordered_map<ItemEnchantCategory,ItemEnchantCategoryData>ENCHANT_CATEGORIES;
|
||||
AbilityDescriptionModifiers modifiers;
|
||||
};
|
||||
|
||||
class Item;
|
||||
|
@ -42,12 +42,25 @@ All rights reserved.
|
||||
INCLUDE_game
|
||||
|
||||
void Monster::STRATEGY::PIRATES_TREASURE(Monster&m,float fElapsedTime,std::string strategy){
|
||||
const float distToPlayer{util::distance(game->GetPlayer()->GetPos(),m.GetPos())};
|
||||
if(distToPlayer<=ConfigFloat("Open Distance"))m.PerformAnimation("OPEN");
|
||||
else m.PerformIdleAnimation();
|
||||
if(m.B(Attribute::COLLIDED_WITH_PLAYER)&&game->GetPlayer()->HasBuff(BuffType::PIRATE_GHOST_CAPTAIN_CURSE_COIN)){
|
||||
game->GetPlayer()->RemoveBuff(BuffType::PIRATE_GHOST_CAPTAIN_PRECURSE);
|
||||
game->GetPlayer()->RemoveBuff(BuffType::PIRATE_GHOST_CAPTAIN_CURSE_COIN);
|
||||
game->GetPlayer()->RemoveBuff(BuffType::PIRATE_GHOST_CAPTAIN_CURSE_DOT);
|
||||
enum Phase{
|
||||
NORMAL,
|
||||
LOCKED,
|
||||
};
|
||||
|
||||
switch(PHASE()){
|
||||
case NORMAL:{
|
||||
const float distToPlayer{util::distance(game->GetPlayer()->GetPos(),m.GetPos())};
|
||||
if(distToPlayer<=ConfigFloat("Open Distance"))m.PerformAnimation("OPEN");
|
||||
else m.PerformIdleAnimation();
|
||||
if(m.B(Attribute::COLLIDED_WITH_PLAYER)&&game->GetPlayer()->HasBuff(BuffType::PIRATE_GHOST_CAPTAIN_CURSE_COIN)){
|
||||
game->GetPlayer()->RemoveBuff(BuffType::PIRATE_GHOST_CAPTAIN_PRECURSE);
|
||||
game->GetPlayer()->RemoveBuff(BuffType::PIRATE_GHOST_CAPTAIN_CURSE_COIN);
|
||||
game->GetPlayer()->RemoveBuff(BuffType::PIRATE_GHOST_CAPTAIN_CURSE_DOT);
|
||||
}
|
||||
}break;
|
||||
case LOCKED:{
|
||||
m.PerformAnimation("LOCKED");
|
||||
m.SetCollisionRadius(m.GetOriginalCollisionRadius()+12);
|
||||
}break;
|
||||
}
|
||||
}
|
@ -2322,4 +2322,8 @@ const bool Player::CoveredInInk()const{
|
||||
}
|
||||
const vf2d&Player::GetPreviousPos()const{
|
||||
return previousPos;
|
||||
}
|
||||
|
||||
const std::unordered_set<std::string>&Player::GetEnchants()const{
|
||||
return enchantList;
|
||||
}
|
@ -340,6 +340,7 @@ public:
|
||||
void SetTestScreenAimingLocation(vf2d forcedAimingLoc);
|
||||
const bool CoveredInInk()const;
|
||||
const vf2d&GetPreviousPos()const; //The position the player was at on the last frame, can be used for comparison purposes to predict where the player may be next.
|
||||
const std::unordered_set<std::string>&GetEnchants()const; //Get all enchants currently affecting the player.
|
||||
private:
|
||||
static std::vector<std::reference_wrapper<Ability>>ABILITY_LIST;
|
||||
const int SHIELD_CAPACITY{32};
|
||||
@ -774,6 +775,7 @@ private:
|
||||
{#class".Right Click Ability.Precast Time"_F,#class".Right Click Ability.Casting Range"_I/100.f*24,#class".Right Click Ability.Casting Size"_I/100.f*24}, \
|
||||
bool( #class".Right Click Ability.CancelCast"_I ) \
|
||||
}; \
|
||||
class::rightClickAbility.abilityConfig=std::ref(DATA.GetProperty(#class".Right Click Ability")); \
|
||||
class::ability1={ \
|
||||
#class".Ability 1.Name"_S, \
|
||||
#class".Ability 1.Short Name"_S, \
|
||||
@ -787,6 +789,7 @@ private:
|
||||
{#class".Ability 1.Precast Time"_F,#class".Ability 1.Casting Range"_I/100.f*24,#class".Ability 1.Casting Size"_I/100.f*24}, \
|
||||
bool(#class".Ability 1.CancelCast"_I) \
|
||||
}; \
|
||||
class::ability1.abilityConfig=std::ref(DATA.GetProperty(#class".Ability 1")); \
|
||||
class::ability2={ \
|
||||
#class".Ability 2.Name"_S, \
|
||||
#class".Ability 2.Short Name"_S, \
|
||||
@ -800,6 +803,7 @@ private:
|
||||
{#class".Ability 2.Precast Time"_F,#class".Ability 2.Casting Range"_I/100.f*24,#class".Ability 2.Casting Size"_I/100.f*24}, \
|
||||
bool(#class".Ability 2.CancelCast"_I) \
|
||||
}; \
|
||||
class::ability2.abilityConfig=std::ref(DATA.GetProperty(#class".Ability 2")); \
|
||||
class::ability3={ \
|
||||
#class".Ability 3.Name"_S, \
|
||||
#class".Ability 3.Short Name"_S, \
|
||||
@ -813,6 +817,7 @@ private:
|
||||
{#class".Ability 3.Precast Time"_F,#class".Ability 3.Casting Range"_I/100.f*24,#class".Ability 3.Casting Size"_I/100.f*24}, \
|
||||
bool(#class".Ability 3.CancelCast"_I) \
|
||||
}; \
|
||||
class::ability3.abilityConfig=std::ref(DATA.GetProperty(#class".Ability 3")); \
|
||||
class::ability4; \
|
||||
Player::ABILITY_LIST.emplace_back(class::original_rightClickAbility); \
|
||||
Player::ABILITY_LIST.emplace_back(class::original_ability1); \
|
||||
|
@ -21,4 +21,9 @@ Adding new class animations
|
||||
Player.txt contains animation names the player has to have loaded.
|
||||
<className>.cpp contains walk and idle animation references that must be loaded in the Initialize() function.
|
||||
Animation.cpp contains the SetupClassWalkIdleAnimations() function which all classes need to implement with their spritesheet and class name (all caps) to create the WALK and IDLE animations in the animation database.
|
||||
All other custom player class animations must be added here too.
|
||||
All other custom player class animations must be added here too.
|
||||
|
||||
Silly Large Purple Wizard Cloak
|
||||
Peace sign on finishing a stage (wink)
|
||||
Kitty Headband
|
||||
Zombie Heart Eyes
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 12140
|
||||
#define VERSION_BUILD 12194
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -1887,7 +1887,7 @@ Monsters
|
||||
Strategy = Pirate's Treasure
|
||||
|
||||
#Size of each animation frame
|
||||
SheetFrameSize = 24,24
|
||||
SheetFrameSize = 36,36
|
||||
|
||||
# Setting this to true means every four rows indicates one animation, the ordering of the directions is: NORTH, EAST, SOUTH, WEST
|
||||
4-Way Spritesheet = False
|
||||
@ -1899,7 +1899,7 @@ Monsters
|
||||
# The First Four animations must represent a standing, walking, attack, and death animation. Their names are up to the creator.
|
||||
IDLE = 1, 1.0, OneShot
|
||||
WALK = 1, 1.0, OneShot
|
||||
SLASHING = 1, 1.0, OneShot
|
||||
LOCKED = 1, 1.0, OneShot
|
||||
OPEN = 1, 1.0, OneShot
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,9 @@ Ranger
|
||||
# Whether or not this ability cancels casts.
|
||||
CancelCast = 0
|
||||
|
||||
Description = Shoots five arrows rapidly at a target location.
|
||||
Description = Shoots {ARROW COUNT} arrows rapidly. Total Damage: {DamageMult:TotalDamageMult}.
|
||||
|
||||
ARROW COUNT = four
|
||||
|
||||
#RGB Values. Color 1 is the circle at full cooldown, Color 2 is the color at empty cooldown.
|
||||
Cooldown Bar Color 1 = 64, 0, 0, 192
|
||||
@ -88,6 +90,8 @@ Ranger
|
||||
# Hitbox radius of the arrows
|
||||
ArrowRadius = 100
|
||||
|
||||
TotalDamageMult = 4.0x
|
||||
|
||||
Sound = Ranger Rapid Fire
|
||||
}
|
||||
Ability 2
|
||||
@ -100,7 +104,7 @@ Ranger
|
||||
# Whether or not this ability cancels casts.
|
||||
CancelCast = 0
|
||||
|
||||
Description = Fires an ultrasonic arrow towards a location, piercing everything it comes in contact with.
|
||||
Description = Fires an ultrasonic arrow towards a location, piercing everything it comes in contact with. Deals {DamageMult:DamageMult} damage.
|
||||
|
||||
#RGB Values. Color 1 is the circle at full cooldown, Color 2 is the color at empty cooldown.
|
||||
Cooldown Bar Color 1 = 64, 0, 0, 192
|
||||
@ -134,7 +138,7 @@ Ranger
|
||||
# Whether or not this ability cancels casts.
|
||||
CancelCast = 0
|
||||
|
||||
Description = The Ranger prepares and fires a fan of densely packed arrows.
|
||||
Description = Prepares and fires a fan of {ArrowCount} packed arrows. Total Damage: {DamageMult:TotalDamageMult}.
|
||||
|
||||
#RGB Values. Color 1 is the circle at full cooldown, Color 2 is the color at empty cooldown.
|
||||
Cooldown Bar Color 1 = 64, 0, 0, 192
|
||||
@ -148,7 +152,8 @@ Ranger
|
||||
DamageMult = 1.0
|
||||
# Number of arrows in the shot spread.
|
||||
ArrowCount = 6
|
||||
# How far the shot spread in one angle is. For example, if the value here is set to 18.375, then Multi shot divides the arrows evenly from a span of -18.375 degrees to the left to 18.375 degrees to the right of the player.
|
||||
TotalDamageMult = 6.0
|
||||
# How far the shot spread in one angle is. For example, if the value here is set to 18.375, then Multishot divides the arrows evenly from a span of -18.375 degrees to the left to 18.375 degrees to the right of the player.
|
||||
MultiShotSpread = 18.375
|
||||
# Speed of arrows that Rapid Fire shoots out.
|
||||
ArrowSpd = 300
|
||||
|
@ -52,7 +52,7 @@ theme_img_directory = themes/
|
||||
# Path to class configuration files
|
||||
class_directory = classes/
|
||||
|
||||
# Class list to be loaded into the game.
|
||||
# Class list to be loaded into the game. SHOULD BE IN ORDER BASED ON Class.h
|
||||
class_list = Warrior, Thief, Ranger, Trapper, Wizard, Witch
|
||||
|
||||
# Items Config
|
||||
|
@ -93,6 +93,17 @@ Item Enchants
|
||||
|
||||
# Stat, Lowest, Highest Value
|
||||
# Stat Modifier[0] = ..., 0, 0
|
||||
|
||||
Ability Settings
|
||||
{
|
||||
# Add variables here to modify what the ability's original description might state.
|
||||
# Use "Pre-Description" and "Post-Description" keys to add to the front or back of a current description string.
|
||||
# Use "Description" key to completely overwrite the default description (be careful of conflicts with another modification!)
|
||||
# Use "Pre-Name" and "Post-Name" keys to add to the front or back of a current ability name.
|
||||
# Use "Name" to completely overwrite the default ability name (be careful of conflicts with another modification!)
|
||||
Pre-Name = Stealthy
|
||||
Post-Description = "Invulnerability time increased by {INVULNERABILITY INCREASE} seconds"
|
||||
}
|
||||
}
|
||||
Poisonous Arrow
|
||||
{
|
||||
@ -115,6 +126,18 @@ Item Enchants
|
||||
|
||||
# Stat, Lowest, Highest Value
|
||||
# Stat Modifier[0] = ..., 0, 0
|
||||
|
||||
Ability Settings
|
||||
{
|
||||
# Add variables here to modify what the ability's original description might state.
|
||||
# Use "Pre-Description" and "Post-Description" keys to add to the front or back of a current description string.
|
||||
# Use "Description" key to completely overwrite the default description (be careful of conflicts with another modification!)
|
||||
# Use "Pre-Name" and "Post-Name" keys to add to the front or back of a current ability name.
|
||||
# Use "Name" to completely overwrite the default ability name (be careful of conflicts with another modification!)
|
||||
Pre-Name = Extreme
|
||||
ARROW COUNT = nine
|
||||
TotalDamageMult = 9.0x
|
||||
}
|
||||
}
|
||||
Charge Beam
|
||||
{
|
||||
@ -125,17 +148,40 @@ Item Enchants
|
||||
|
||||
# Stat, Lowest, Highest Value
|
||||
# Stat Modifier[0] = ..., 0, 0
|
||||
|
||||
Ability Settings
|
||||
{
|
||||
# Add variables here to modify what the ability's original description might state.
|
||||
# Use "Pre-Description" and "Post-Description" keys to add to the front or back of a current description string.
|
||||
# Use "Description" key to completely overwrite the default description (be careful of conflicts with another modification!)
|
||||
# Use "Pre-Name" and "Post-Name" keys to add to the front or back of a current ability name.
|
||||
# Use "Name" to completely overwrite the default ability name (be careful of conflicts with another modification!)
|
||||
Name = "Charge Beam"
|
||||
Post-Description = "Width is massively increased."
|
||||
}
|
||||
}
|
||||
Mega Charged Shot
|
||||
{
|
||||
Description = "Charged Shot's cast time increases by {CAST TIME INCREASE} seconds. Now deals {DAMAGE INCREASE MULT}x more damage."
|
||||
Affects = Ability 2
|
||||
|
||||
CAST TIME INCREASE = 1.5s
|
||||
DAMAGE INCREASE MULT = 2x
|
||||
CAST TIME INCREASE = 1.5
|
||||
DAMAGE INCREASE MULT = 2
|
||||
|
||||
# Stat, Lowest, Highest Value
|
||||
# Stat Modifier[0] = ..., 0, 0
|
||||
|
||||
Ability Settings
|
||||
{
|
||||
# Add variables here to modify what the ability's original description might state.
|
||||
# Use "Pre-Description" and "Post-Description" keys to add to the front or back of a current description string.
|
||||
# Use "Description" key to completely overwrite the default description (be careful of conflicts with another modification!)
|
||||
# Use "Pre-Name" and "Post-Name" keys to add to the front or back of a current ability name.
|
||||
# Use "Name" to completely overwrite the default ability name (be careful of conflicts with another modification!)
|
||||
Pre-Name = "Mega"
|
||||
DamageMult = 5.0
|
||||
Post-Description = Cast time increased by {CAST TIME INCREASE} seconds.
|
||||
}
|
||||
}
|
||||
Multi-Multishot
|
||||
{
|
||||
@ -147,6 +193,17 @@ Item Enchants
|
||||
|
||||
# Stat, Lowest, Highest Value
|
||||
# Stat Modifier[0] = ..., 0, 0
|
||||
|
||||
Ability Settings
|
||||
{
|
||||
# Add variables here to modify what the ability's original description might state.
|
||||
# Use "Pre-Description" and "Post-Description" keys to add to the front or back of a current description string.
|
||||
# Use "Description" key to completely overwrite the default description (be careful of conflicts with another modification!)
|
||||
# Use "Pre-Name" and "Post-Name" keys to add to the front or back of a current ability name.
|
||||
# Use "Name" to completely overwrite the default ability name (be careful of conflicts with another modification!)
|
||||
Pre-Name = "Multi-"
|
||||
Post-Description = "Holds up to {EXTRA CHARGE COUNT} charges. Cooldown Reduced by {COOLDOWN REDUCTION PCT}."
|
||||
}
|
||||
}
|
||||
}
|
||||
Thief
|
||||
|
@ -7,6 +7,9 @@ ItemConfiguration
|
||||
Equipment = Equipment.txt
|
||||
Weapons = Weapons.txt
|
||||
Accessories = Accessories.txt
|
||||
|
||||
# Item enchants unit testing config
|
||||
Item Enchants Test Config = ItemEnchants-test.txt
|
||||
}
|
||||
Item
|
||||
{
|
||||
|
Binary file not shown.
@ -3574,7 +3574,7 @@ namespace olc
|
||||
else if (c=='#')
|
||||
{
|
||||
skip=6;
|
||||
textCol=BLACK;
|
||||
textCol={0,0,0,col.a};
|
||||
for(int i=1;i<7;i++){
|
||||
if(i<3){
|
||||
textCol.r*=16;
|
||||
@ -3687,7 +3687,7 @@ namespace olc
|
||||
else if (c=='#')
|
||||
{
|
||||
skip=6;
|
||||
textCol=BLACK;
|
||||
textCol={0,0,0,col.a};
|
||||
for(int i=1;i<7;i++){
|
||||
if(i<3){
|
||||
textCol.r*=16;
|
||||
@ -4256,7 +4256,7 @@ namespace olc
|
||||
else if (c=='#')
|
||||
{
|
||||
skip=6;
|
||||
textCol=BLACK;
|
||||
textCol={0,0,0,col.a};
|
||||
for(int i=1;i<7;i++){
|
||||
if(i<3){
|
||||
textCol.r*=16;
|
||||
@ -4491,7 +4491,7 @@ namespace olc
|
||||
else if (c=='#')
|
||||
{
|
||||
skip=6;
|
||||
textCol=BLACK;
|
||||
textCol={0,0,0,col.a};
|
||||
for(int i=1;i<7;i++){
|
||||
if(i<3){
|
||||
textCol.r*=16;
|
||||
|
@ -546,6 +546,10 @@ namespace olc::utils
|
||||
return m_vecObjects[m_mapObjects[name]].second;
|
||||
}
|
||||
|
||||
inline const datafile&at(const std::string&name)const{
|
||||
return m_vecObjects.at(m_mapObjects.at(name)).second;
|
||||
}
|
||||
|
||||
inline auto begin(){
|
||||
return GetKeys().begin();
|
||||
}
|
||||
|
Binary file not shown.
88
x64/Unit Testing/assets/config/items/Accessories-test.txt
Normal file
88
x64/Unit Testing/assets/config/items/Accessories-test.txt
Normal file
@ -0,0 +1,88 @@
|
||||
Fragment Description = "A small piece of concentrated material from broken down jewelry."
|
||||
# Number of fragments earned when breaking down an accessory.
|
||||
Fragment Disassemble Gain Amount = 1
|
||||
# Number of fragments and gold required to Refine an accessory.
|
||||
Fragment Refine Cost = 1, 20g
|
||||
# Number of fragments and gold required to Enchant an accessory.
|
||||
Fragment Enchant Cost = 3, 35g
|
||||
|
||||
# How much to increase refined stats by with each refinement. (Ex. if the value is 20%, it takes 5 refinements at most from an item with the lowest possible stat to the max stat with 20% increments.)
|
||||
Refine Stat Increase Amount = 20%
|
||||
|
||||
Equipment
|
||||
{
|
||||
Ring of the Slime King
|
||||
{
|
||||
Slot = Ring1,Ring2
|
||||
ItemCategory = Accessories
|
||||
|
||||
Fragment Name = Slime King Ring Fragment
|
||||
# Uncomment to specify a custom icon for this fragment. Otherwise uses the default fragment icon with auto-detected color sampling.
|
||||
#Fragment Icon = MyIcon.png
|
||||
|
||||
# See ItemStats.txt for valid stat names
|
||||
StatValues = Health,Mana,Move Spd %
|
||||
MinStats = 5,1,1
|
||||
MaxStats = 20,4,3
|
||||
SellValue = 90
|
||||
|
||||
Equip Sound = Equip Accessory
|
||||
}
|
||||
Ring of the Bear
|
||||
{
|
||||
Slot = Ring1,Ring2
|
||||
ItemCategory = Accessories
|
||||
|
||||
Fragment Name = Bear Ring Fragment
|
||||
|
||||
# See ItemStats.txt for valid stat names
|
||||
StatValues = Health,Attack,Mana
|
||||
MinStats = 4,1,1
|
||||
MaxStats = 10,4,3
|
||||
SellValue = 75
|
||||
|
||||
Equip Sound = Equip Accessory
|
||||
}
|
||||
Stone Ring
|
||||
{
|
||||
Slot = Ring1,Ring2
|
||||
ItemCategory = Accessories
|
||||
|
||||
Fragment Name = Stone Ring Fragment
|
||||
|
||||
# See ItemStats.txt for valid stat names
|
||||
StatValues = Defense,Health,Health %
|
||||
MinStats = 5,10,1
|
||||
MaxStats = 15,25,3
|
||||
SellValue = 130
|
||||
|
||||
Equip Sound = Equip Accessory
|
||||
}
|
||||
Bird's Treasure
|
||||
{
|
||||
Slot = Ring1,Ring2
|
||||
ItemCategory = Accessories
|
||||
|
||||
Fragment Name = Bird's Treasure Fragment
|
||||
|
||||
# See ItemStats.txt for valid stat names
|
||||
StatValues = Move Spd %,Crit Rate,Mana
|
||||
MinStats = 1,1,2
|
||||
MaxStats = 5,3,5
|
||||
SellValue = 110
|
||||
|
||||
Equip Sound = Equip Accessory
|
||||
}
|
||||
Null Ring
|
||||
{
|
||||
Slot = Ring1,Ring2
|
||||
ItemCategory = Accessories
|
||||
|
||||
Fragment Name = Null Ring Fragment
|
||||
|
||||
SellValue = 110
|
||||
|
||||
Equip Sound = Equip Accessory
|
||||
|
||||
}
|
||||
}
|
35
x64/Unit Testing/assets/config/items/ItemEnchants-test.txt
Normal file
35
x64/Unit Testing/assets/config/items/ItemEnchants-test.txt
Normal file
@ -0,0 +1,35 @@
|
||||
Item Enchants
|
||||
{
|
||||
General Enchants
|
||||
{
|
||||
|
||||
}
|
||||
Class Enchants
|
||||
{
|
||||
Ranger
|
||||
{
|
||||
Test Enchant
|
||||
{
|
||||
Description = "A test enchant"
|
||||
Affects = Ability 1
|
||||
|
||||
Ability Settings
|
||||
{
|
||||
# Add variables here to modify what the ability's original description might state.
|
||||
# Use "Pre-Description" and "Post-Description" keys to add to the front or back of a current description string.
|
||||
# Use "Description" key to completely overwrite the default description (be careful of conflicts with another modification!)
|
||||
# Use "Pre-Name" and "Post-Name" keys to add to the front or back of a current ability name.
|
||||
# Use "Name" to completely overwrite the default ability name (be careful of conflicts with another modification!)
|
||||
Pre-Name = Test
|
||||
Name = Enchant
|
||||
Pre-Description = "Pre test"
|
||||
Description = "My Description"
|
||||
Post-Description = "Post test"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Unique Enchants
|
||||
{
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user