All checks were successful
Emscripten Build / Build_and_Deploy_Web_Build (push) Successful in 6m49s
217 lines
9.4 KiB
C++
217 lines
9.4 KiB
C++
#pragma region License
|
|
/*
|
|
License (OLC-3)
|
|
~~~~~~~~~~~~~~~
|
|
|
|
Copyright 2024 Joshua 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 "Ability.h"
|
|
#include "AdventuresInLestoria.h"
|
|
|
|
INCLUDE_game
|
|
|
|
PrecastData::PrecastData()
|
|
:castTime(0),range(0),size(0){};
|
|
PrecastData::PrecastData(float castTime)
|
|
:castTime(castTime),range(0),size(0),precastTargetingRequired(castTime>0){};
|
|
PrecastData::PrecastData(float castTime,float range,float size)
|
|
:castTime(castTime),range(range),size(size),precastTargetingRequired(range>0||castTime>0){};
|
|
|
|
InputGroup Ability::DEFAULT;
|
|
|
|
float Ability::iconMouseoverTime{};
|
|
float Ability::alphaMouseoverTime{};
|
|
std::string Ability::tooltipText{""};
|
|
std::string Ability::tooltipTitle{""};
|
|
Pixel Ability::tooltipTitleCol{};
|
|
|
|
Ability::Ability()
|
|
:name("???"),shortName("???"),description("???"),cooldown(0),COOLDOWN_TIME(0),input(&DEFAULT){};
|
|
Ability::Ability(std::string name,std::string shortName,std::string description,float cooldownTime,int manaCost,InputGroup*input,std::string icon,Pixel barColor1,Pixel barColor2,PrecastData precastInfo,bool canCancelCast)
|
|
:name(name),shortName(shortName),description(description),cooldown(0),COOLDOWN_TIME(cooldownTime),manaCost(manaCost),input(input),icon(icon),barColor1(barColor1),barColor2(barColor2),precastInfo(precastInfo),canCancelCast(canCancelCast){}
|
|
|
|
const float Ability::GetCooldownTime()const{
|
|
return COOLDOWN_TIME;
|
|
}
|
|
|
|
const bool Ability::operator==(const Ability&a)const{
|
|
return name==a.name&&isOriginalAbility==a.isOriginalAbility;
|
|
}
|
|
|
|
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 {
|
|
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((*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 {
|
|
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()));
|
|
}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;
|
|
} |