Implemented util::Tokenize and appropriate unit test. Refactored ability description parsing function slightly to handle future delimiters. Release Build 13626.
This commit is contained in:
parent
4862652593
commit
c9db9209d7
@ -37,6 +37,7 @@ All rights reserved.
|
||||
#pragma endregion
|
||||
#include "Ability.h"
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include<ranges>
|
||||
|
||||
INCLUDE_game
|
||||
|
||||
@ -113,38 +114,68 @@ const std::string Ability::GetDescriptionWithPlayerModifiers()const{
|
||||
};
|
||||
const Pixel specialValCol{69,249,255};
|
||||
|
||||
const auto FindAndParse=[&specialPrefixes,&specialValCol](datafile&data,mutable std::string&finalText,mutable bool&bracesFound,mutable std::string&variableName)->bool{
|
||||
if(data.HasProperty(variableName)){
|
||||
finalText+=specialValCol.toHTMLColorCode()+data.GetProperty(variableName).GetFullString()+WHITE.toHTMLColorCode();
|
||||
bracesFound=false;
|
||||
variableName="";
|
||||
return true;
|
||||
}else {
|
||||
enum SymbolIndicator{
|
||||
MULTIPLICATION, //*
|
||||
KEY_VALUE_PAIR, //:
|
||||
NOT_FOUND,
|
||||
};
|
||||
|
||||
const auto AddToDescription=[&finalText,&bracesFound,&variableName](const std::string&descriptionTextAddon){
|
||||
finalText+=descriptionTextAddon;
|
||||
bracesFound=false;
|
||||
variableName="";
|
||||
};
|
||||
|
||||
SymbolIndicator indicator{NOT_FOUND};
|
||||
if(variableName.find(':')!=std::string::npos)indicator=KEY_VALUE_PAIR;
|
||||
else if(variableName.find('*')!=std::string::npos)indicator=MULTIPLICATION;
|
||||
switch(indicator){
|
||||
case MULTIPLICATION:{
|
||||
std::vector<std::string>tokens{util::Tokenize(variableName,'*')};
|
||||
std::optional<float>numb{};
|
||||
for(const std::string&token:tokens){
|
||||
if(!numb)numb=std::stof(data.GetProperty(token).GetString());
|
||||
else *numb*=std::stof(data.GetProperty(token).GetString());
|
||||
}
|
||||
if(!numb)ERR("WARNING! Somehow did not populate a number. Variable: "<<variableName);
|
||||
AddToDescription(specialValCol.toHTMLColorCode()+std::format("{:.2}",*numb)+WHITE.toHTMLColorCode());
|
||||
return true;
|
||||
}break;
|
||||
case KEY_VALUE_PAIR:{
|
||||
std::vector<std::string>tokens{util::Tokenize(variableName,':')};
|
||||
if(tokens.size()!=2)ERR(": variable syntax only allows 2 arguments. Ex. Key:Value. Arguments found: "<<tokens.size());
|
||||
std::string separatorKey{tokens.at(0)};
|
||||
std::string separatorVal{tokens.at(1)};
|
||||
if(!specialPrefixes.count(separatorKey))ERR(std::format("Could not find translation function for key {} inside special prefixes map!",separatorKey))
|
||||
else {
|
||||
if(!data.HasProperty(separatorVal))return false; //Could not be found in this section, will need to seek in another location.
|
||||
AddToDescription(specialValCol.toHTMLColorCode()+specialPrefixes[separatorKey](data,separatorVal)+WHITE.toHTMLColorCode());
|
||||
return true;
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
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 {
|
||||
if(!data.HasProperty(separatorVal))return false; //Could not be found in this section, will need to seek in another location.
|
||||
finalText+=specialValCol.toHTMLColorCode()+specialPrefixes[separatorKey](data,separatorVal)+WHITE.toHTMLColorCode();
|
||||
bracesFound=false;
|
||||
variableName="";
|
||||
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()));
|
||||
if(!FindAndParse((*abilityConfig).get(),finalText,bracesFound,variableName))ERR(std::format("Could not find variable {} for Ability {}",variableName,GetName()));
|
||||
}else if(bracesFound)variableName+=c;
|
||||
else finalText+=c;
|
||||
marker++;
|
||||
@ -170,34 +201,16 @@ const std::string Ability::GetDescriptionWithPlayerModifiers()const{
|
||||
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 {
|
||||
if(!data.HasProperty(separatorVal))return false; //Could not be found in this section, will need to seek in another location.
|
||||
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()));
|
||||
const bool FoundVariable{
|
||||
FindAndParse(enchant.get().GetData()["Ability Settings"],finalText,bracesFound,variableName)||
|
||||
FindAndParse(enchant.get().GetData(),finalText,bracesFound,variableName)||
|
||||
FindAndParse((*(*enchant.get().GetAbility())->abilityConfig).get(),finalText,bracesFound,variableName)
|
||||
};
|
||||
if(!FoundVariable)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++;
|
||||
|
||||
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 13607
|
||||
#define VERSION_BUILD 13626
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
||||
@ -60,7 +60,7 @@ Thief
|
||||
{
|
||||
Name = Hidden Dagger
|
||||
Short Name = DAGGER
|
||||
Description = Jump backwards while throwing a dagger.
|
||||
Description = Jump backwards while throwing a dagger. The dagger deals {DamageMult:Damage}
|
||||
Icon = hidden_dagger.png
|
||||
Cooldown = 8
|
||||
Mana Cost = 20
|
||||
|
||||
@ -241,7 +241,7 @@ Wizard
|
||||
FireRingDamageMult = 1
|
||||
# How often the fire ring deals damage to enemies inside of it.
|
||||
FireRingDamageFreq = 1
|
||||
FireRingLifetime = 4
|
||||
FireRingLifetime = 4.1000
|
||||
|
||||
WorldShakeTime = 2
|
||||
|
||||
|
||||
@ -188,3 +188,13 @@ TEST(EngineTests,"ClassUtilTest"){
|
||||
REQUIRE("Witch"==classutils::ClassToString(Class::WITCH));
|
||||
REQUIRE("Trapper"==classutils::ClassToString(Class::TRAPPER));
|
||||
}
|
||||
|
||||
TEST(EngineTests,"TokenizeFunctionTest"){
|
||||
REQUIRE_THROWS_AS(util::Tokenize("",','),std::runtime_error);
|
||||
REQUIRE_THAT(util::Tokenize("1,2,3",','),Catch::Matchers::Equals(std::vector<std::string>{"1","2","3"}));
|
||||
REQUIRE_THROWS_AS(util::Tokenize("1,2,,3",','),std::runtime_error);
|
||||
REQUIRE_THROWS_AS(util::Tokenize("1,2,3,",','),std::runtime_error);
|
||||
REQUIRE_THROWS_AS(util::Tokenize(",",','),std::runtime_error);
|
||||
REQUIRE_THAT(util::Tokenize("1,2:3",':'),Catch::Matchers::Equals(std::vector<std::string>{"1,2","3"}));
|
||||
REQUIRE_THAT(util::Tokenize("1,2:3:4:5:6:7:AB:;:1 0:11,12",':'),Catch::Matchers::Equals(std::vector<std::string>{"1,2","3","4","5","6","7","AB",";","1 0","11,12",}));
|
||||
}
|
||||
@ -255,4 +255,20 @@ const std::string util::GetCaseInsensitiveFilename(const std::string&filename){
|
||||
}
|
||||
ERR(std::format("WARNING! Could not find or match case for filename {}! THIS SHOULD NOT BE HAPPENING!",filename));
|
||||
std::unreachable();
|
||||
}
|
||||
|
||||
const std::vector<std::string>util::Tokenize(const std::string&str,const char separatorChar){
|
||||
std::vector<std::string>tokens;
|
||||
size_t marker{};
|
||||
size_t lastTokenInd{};
|
||||
while((marker=str.find_first_of(separatorChar,lastTokenInd))!=std::string::npos){
|
||||
const std::string token{str.substr(lastTokenInd,marker-lastTokenInd)};
|
||||
lastTokenInd=marker+1;
|
||||
if(token.length()==0)ERR("WARNING! A blank token was found! THIS SHOULD NOT BE HAPPENING! Input string:"<<str)
|
||||
tokens.emplace_back(token);
|
||||
}
|
||||
const std::string token{str.substr(lastTokenInd)};
|
||||
if(token.length()==0)ERR("WARNING! A blank token was found! THIS SHOULD NOT BE HAPPENING! Input string:"<<str)
|
||||
tokens.emplace_back(token);
|
||||
return tokens;
|
||||
}
|
||||
@ -122,6 +122,8 @@ namespace olc::util{
|
||||
const std::string toLower(const std::string oldStr);
|
||||
|
||||
const std::string GetCaseInsensitiveFilename(const std::string&filename);
|
||||
|
||||
const std::vector<std::string>Tokenize(const std::string&str,const char separatorChar);
|
||||
}
|
||||
|
||||
template<class TL, class TR>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user