Add dynamic item description parsing and modifying based on ability enchantments for ability tooltips. Fixed bug with the transparency of drawn text not being preserved when using HTML color codes in text with alpha transparency. Release Build 12186.
Some checks failed
Emscripten Build / Build_and_Deploy_Web_Build (push) Has been cancelled

This commit is contained in:
sigonasr2 2025-05-12 19:18:07 -05:00
parent cb3f38e07c
commit b43e6e5bf1
6 changed files with 82 additions and 18 deletions

View File

@ -92,8 +92,58 @@ const std::string Ability::GetNameWithPlayerModifiers()const{
}
const std::string Ability::GetDescriptionWithPlayerModifiers()const{
using SpecialKey=std::string;
using TranslateFunc=std::function<std::string(const std::string&val)>;
std::unordered_map<SpecialKey,TranslateFunc>specialPrefixes{
#define TranslateFunc [&](const std::string&val)->std::string
{"DamageMult",TranslateFunc{
float damageMult{stof((*abilityConfig).get()[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](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{description};
std::string newDescription{ParseVariables(description)};
std::string suffixDescription{};
for(const auto&enchant:ItemEnchantInfo::GetAllEnchantsAffectingAbility(name)){
const ItemEnchantInfo::AbilityDescriptionModifiers&modifiers{enchant.get().GetModifiers()};
@ -103,23 +153,32 @@ const std::string Ability::GetDescriptionWithPlayerModifiers()const{
if(suffixDescription.length()>0&&modifiers.preDescription)suffixDescription+=" ";
suffixDescription+=modifiers.postDescription.value_or("");
const auto ParseVariables=[&](const std::string_view abilityText)->std::string{
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](datafile&data)->bool{
const auto FindAndParse=[&finalText,&bracesFound,&variableName,&specialPrefixes,&specialValCol](datafile&data)->bool{
if(data.HasProperty(variableName)){
finalText+=data.GetProperty(variableName).GetFullString();
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](separatorVal)+WHITE.toHTMLColorCode();
bracesFound=false;
return true;
}
}
return false;
};
while(abilityText.length()>marker){
while(marker<abilityText.length()){
const char c{abilityText[marker]};
if(!bracesFound&&c=='{')bracesFound=true;
else if(bracesFound&&c=='}'){ //Parse the variable.
@ -133,9 +192,14 @@ const std::string Ability::GetDescriptionWithPlayerModifiers()const{
}
return finalText;
};
prefixDescription=ParseVariables(prefixDescription);
newDescription=ParseVariables(newDescription);
suffixDescription=ParseVariables(suffixDescription);
prefixDescription=ParseVariablesForEnchant(prefixDescription);
newDescription=ParseVariablesForEnchant(newDescription);
suffixDescription=ParseVariablesForEnchant(suffixDescription);
}
return std::format("{}{}{}",prefixDescription,newDescription,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;
}

View File

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1
#define VERSION_MINOR 3
#define VERSION_PATCH 0
#define VERSION_BUILD 12173
#define VERSION_BUILD 12186
#define stringify(a) stringify_(a)
#define stringify_(a) #a

View File

@ -64,7 +64,7 @@ Ranger
# Whether or not this ability cancels casts.
CancelCast = 0
Description = Shoots {ARROW COUNT} arrows rapidly. Total Damage: {DamageMult:TotalDamageMult}
Description = Shoots {ARROW COUNT} arrows rapidly. Total Damage: {DamageMult:TotalDamageMult}.
ARROW COUNT = four
@ -104,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. Deals {DamageMult} damage.
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
@ -138,7 +138,7 @@ Ranger
# Whether or not this ability cancels casts.
CancelCast = 0
Description = Prepares and fires a fan of {ArrowCount} packed arrows. Total Damage: {DamageMult}
Description = Prepares and fires a fan of {ArrowCount} packed arrows. Total Damage: {DamageMult:DamageMult}.
#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

View File

@ -180,7 +180,7 @@ Item Enchants
# 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}."
Post-Description = Cast time increased by {CAST TIME INCREASE} seconds.
}
}
Multi-Multishot

View File

@ -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;