Added operator< for Pixel class to allow sets of pixels to be used. Add fragment item default description. Generate fragment images that randomly sample from the source ring's colors. Add base fragment item icon. Release Build 10443.

removeExposedPackKey
sigonasr2 4 months ago
parent 47530d4822
commit 13eeb46000
  1. 8
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 19
      Adventures in Lestoria/ArtificerRefineWindow.cpp
  3. 2
      Adventures in Lestoria/BearTrap.cpp
  4. 47
      Adventures in Lestoria/Item.cpp
  5. 1
      Adventures in Lestoria/Item.h
  6. 5
      Adventures in Lestoria/Pixel.cpp
  7. 1
      Adventures in Lestoria/Pixel.h
  8. 2
      Adventures in Lestoria/Version.h
  9. 1
      Adventures in Lestoria/assets/config/gfx/gfx.txt
  10. 12
      Adventures in Lestoria/assets/config/items/Accessories.txt
  11. BIN
      Adventures in Lestoria/assets/gamepack.pak
  12. BIN
      Adventures in Lestoria/assets/items/Fragment.png
  13. BIN
      x64/Release/Adventures in Lestoria.exe

@ -3578,10 +3578,6 @@ void AiL::InitializeGraphics(){
GFX.Reset(); GFX.Reset();
Menu::themes.Reset(); Menu::themes.Reset();
//These two create item graphics, so they should be after the GFX structure gets reset!
ItemAttribute::Initialize();
ItemInfo::InitializeItems();
circleCooldownPoints.push_back({0,0}); circleCooldownPoints.push_back({0,0});
squareCircleCooldownPoints.push_back({0,0}); squareCircleCooldownPoints.push_back({0,0});
for(int i=0;i<=360;i+=4){ for(int i=0;i<=360;i+=4){
@ -3657,6 +3653,10 @@ void AiL::InitializeGraphics(){
} }
} }
//These two create item graphics, so they should be after the GFX structure gets reset!
ItemAttribute::Initialize();
ItemInfo::InitializeItems();
for(std::string img:VisualNovel::graphicsToLoad){ for(std::string img:VisualNovel::graphicsToLoad){
Renderable&image=GFX[img]; Renderable&image=GFX[img];
LoadResource(image,"GFX_Prefix"_S+img); LoadResource(image,"GFX_Prefix"_S+img);

@ -38,11 +38,28 @@ All rights reserved.
#include "Menu.h" #include "Menu.h"
#include "AdventuresInLestoria.h" #include "AdventuresInLestoria.h"
#include "RowInventoryScrollableWindowComponent.h"
#include "MenuLabel.h"
INCLUDE_game INCLUDE_game
void Menu::InitializeArtificerRefineWindow(){ void Menu::InitializeArtificerRefineWindow(){
Menu*artificerRefineWindow=CreateMenu(ARTIFICER_REFINE,CENTERED,vi2d{144,144}); Menu*artificerRefineWindow=CreateMenu(ARTIFICER_REFINE,CENTERED,game->GetScreenSize()-vi2d{52,52});
auto inventoryLabel=artificerRefineWindow->ADD("Accessory List Label",MenuLabel)(geom2d::rect<float>{{},{180.f,12.f}},"Choose Accessory:",1.f,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN)END;
auto inventoryDisplay=artificerRefineWindow->ADD("Accessory List",RowInventoryScrollableWindowComponent)(geom2d::rect<float>{{0.f,16.f},{artificerRefineWindow->size.x/2-4.f,artificerRefineWindow->size.y-32}},"","",[](MenuFuncData data){
return true;
},DO_NOTHING,DO_NOTHING,
InventoryCreator::RowPlayer_InventoryUpdate,
InventoryWindowOptions{.padding=1,.size={137,28}})END;
auto backButton=artificerRefineWindow->ADD("Back",MenuComponent)(geom2d::rect<float>{{0.f,artificerRefineWindow->size.y-12.f},{120.f,12.f}},"Back",[](MenuFuncData data){
Menu::CloseMenu();
return true;
})END;
Menu::AddInventoryListener(inventoryDisplay,"Accessories");
artificerRefineWindow->SetupKeyboardNavigation( artificerRefineWindow->SetupKeyboardNavigation(
[](MenuType type,Data&returnData){ //On Open [](MenuType type,Data&returnData){ //On Open

@ -67,7 +67,7 @@ BulletDestroyState BearTrap::MonsterHit(Monster&monster,const uint8_t markStacks
const float timeBetweenTicks{"Trapper.Ability 2.Marked Target Bleed"_f[2]}; const float timeBetweenTicks{"Trapper.Ability 2.Marked Target Bleed"_f[2]};
if(markStacksBeforeHit>0){ if(markStacksBeforeHit>0){
const uint8_t resetStackCount{uint8_t("Trapper.Ability 2.Marked Target Stack Count Reset"_I)+1U}; //Add an additional stack because we know the target hit is about to lose one stack. const uint8_t resetStackCount{uint8_t("Trapper.Ability 2.Marked Target Stack Count Reset"_I+1U)}; //Add an additional stack because we know the target hit is about to lose one stack.
const uint8_t numberOfStacksToReplenish{uint8_t(resetStackCount-monster.GetMarkStacks())}; const uint8_t numberOfStacksToReplenish{uint8_t(resetStackCount-monster.GetMarkStacks())};
monster.ApplyMark("Trapper.Ability 2.Marked Target Reset Time"_F,numberOfStacksToReplenish); monster.ApplyMark("Trapper.Ability 2.Marked Target Reset Time"_F,numberOfStacksToReplenish);
monster.ApplyDot(bleedDuration,bleedDamage,timeBetweenTicks); monster.ApplyDot(bleedDuration,bleedDamage,timeBetweenTicks);

@ -151,6 +151,7 @@ void ItemInfo::InitializeItems(){
bool useDuringCast=false; bool useDuringCast=false;
std::unordered_set<std::string>equippableClass; std::unordered_set<std::string>equippableClass;
EventName useSound; EventName useSound;
std::optional<std::string>fragmentName;
for(auto&[itemKey,itemValue]:data[key].GetKeys()){ for(auto&[itemKey,itemValue]:data[key].GetKeys()){
std::string keyName=itemKey; std::string keyName=itemKey;
if(keyName=="Description"){ if(keyName=="Description"){
@ -199,6 +200,9 @@ void ItemInfo::InitializeItems(){
if(keyName.starts_with("Alternative Name")){ if(keyName.starts_with("Alternative Name")){
if(ITEM_CONVERSIONS.count(data[key][keyName].GetString()))ERR(std::format("Item {} already exists in Item Conversion database! Cannot add a duplicate entry!",data[key][keyName].GetString())); if(ITEM_CONVERSIONS.count(data[key][keyName].GetString()))ERR(std::format("Item {} already exists in Item Conversion database! Cannot add a duplicate entry!",data[key][keyName].GetString()));
ITEM_CONVERSIONS[data[key][keyName].GetString()]=key; ITEM_CONVERSIONS[data[key][keyName].GetString()]=key;
}else
if(keyName.starts_with("Fragment Name")){
fragmentName=data[key][keyName].GetString();
}else{ //THis is a custom override modifier for a script. NO-OP }else{ //THis is a custom override modifier for a script. NO-OP
} }
} }
@ -320,6 +324,7 @@ void ItemInfo::InitializeItems(){
it.useFunc=scriptName; it.useFunc=scriptName;
it.minStats=minStats; it.minStats=minStats;
it.maxStats=maxStats; it.maxStats=maxStats;
it.fragmentName=fragmentName;
#pragma region Equipment Category Verification Tests #pragma region Equipment Category Verification Tests
int equipmentCategories=0; int equipmentCategories=0;
@ -334,6 +339,7 @@ void ItemInfo::InitializeItems(){
if(it.Category()=="Accessories"&&it.IsWeapon())ERR(std::format("WARNING! {} is in the Accessories Category, but is considered a Weapon!",it.Name())) if(it.Category()=="Accessories"&&it.IsWeapon())ERR(std::format("WARNING! {} is in the Accessories Category, but is considered a Weapon!",it.Name()))
if(it.Category()=="Accessories"&&it.IsArmor())ERR(std::format("WARNING! {} is in the Accessories Category, but is considered Armor!",it.Name())) if(it.Category()=="Accessories"&&it.IsArmor())ERR(std::format("WARNING! {} is in the Accessories Category, but is considered Armor!",it.Name()))
if(it.Category()=="Accessories"&&!it.IsAccessory())ERR(std::format("WARNING! {} is in the Accessories Category, but not considered an Accessory!",it.Name())) if(it.Category()=="Accessories"&&!it.IsAccessory())ERR(std::format("WARNING! {} is in the Accessories Category, but not considered an Accessory!",it.Name()))
if(it.IsAccessory()&&!it.fragmentName.has_value())ERR(std::format("WARNING! Accessory {} does not have a \"Fragment Name\" set!",it.Name()));
#pragma endregion #pragma endregion
#pragma region Equipment Sort Rules Verification Tests #pragma region Equipment Sort Rules Verification Tests
@ -350,16 +356,47 @@ void ItemInfo::InitializeItems(){
std::sort(craftableConsumables.begin(),craftableConsumables.end(),[](std::shared_ptr<Item>&item1,std::shared_ptr<Item>&item2){return item1.get()->GetEnhancementInfo()[0].chapterAvailable<item2.get()->GetEnhancementInfo()[0].chapterAvailable;}); std::sort(craftableConsumables.begin(),craftableConsumables.end(),[](std::shared_ptr<Item>&item1,std::shared_ptr<Item>&item2){return item1.get()->GetEnhancementInfo()[0].chapterAvailable<item2.get()->GetEnhancementInfo()[0].chapterAvailable;});
ITEM_DATA.SetInitialized();
ITEM_CATEGORIES.SetInitialized();
ITEM_CONVERSIONS.SetInitialized();
Menu::LockInListeners();
for(auto&[name,info]:ITEM_DATA){ for(auto&[name,info]:ITEM_DATA){
Item tempItem{1,name}; Item tempItem{1,name};
if(tempItem.Description().length()==0)ERR("WARNING! Item "<<info.name<<" does not have a description!"); if(tempItem.Description().length()==0)ERR("WARNING! Item "<<info.name<<" does not have a description!");
} }
CreateAccessoryFragments:{
for(const auto&itemName:ITEM_CATEGORIES.at("Accessories")){
const std::string fragmentName{ITEM_DATA.at(itemName).fragmentName.value()};
ItemInfo&it{ITEM_DATA[fragmentName]};
//olc::Decal*generatedFragmentImage{new olc::Decal(new Sprite(24,24))};
GFX[fragmentName].Create(24,24);
game->SetDrawTarget(GFX.at(fragmentName).Sprite());
std::set<Pixel>colors;
for(int y=0;y<24;y++){
for(int x=0;x<24;x++){
colors.insert(ITEM_DATA.at(itemName).img->sprite->GetPixel(x,y));
}
}
colors.erase(BLANK);
game->DrawSprite({},GFX.at("items/Fragment.png").Sprite(),1U,0U,[colors](const Pixel&in){
if(in==BLANK)return in;
for(const Pixel&p:colors){
if(util::random()%colors.size()==0)return PixelLerp(in,{p.r,p.g,p.b},0.5f);
}
return in;
});
game->SetDrawTarget(nullptr);
GFX.at(fragmentName).Decal()->Update();
it.img=GFX.at(fragmentName).Decal();
it.name=fragmentName;
it.description="Fragment Description"_S;
it.category="Materials";
LOG(std::format("Item Fragment {} generated...",fragmentName));
}
}
ITEM_DATA.SetInitialized();
ITEM_CATEGORIES.SetInitialized();
ITEM_CONVERSIONS.SetInitialized();
Menu::LockInListeners();
LOG(ITEM_DATA.size()<<" items have been loaded."); LOG(ITEM_DATA.size()<<" items have been loaded.");
LOG(ITEM_CATEGORIES.size()<<" item categories have been loaded."); LOG(ITEM_CATEGORIES.size()<<" item categories have been loaded.");
} }

@ -335,6 +335,7 @@ class ItemInfo{
std::unordered_set<std::string>equippableClass; std::unordered_set<std::string>equippableClass;
Stats minStats; Stats minStats;
Stats maxStats; Stats maxStats;
std::optional<std::string>fragmentName;
private: private:
static void InitializeScripts(); static void InitializeScripts();
static void InitializeSets(); static void InitializeSets();

@ -154,6 +154,11 @@ namespace olc{
return *this; return *this;
} }
bool Pixel::operator< (const Pixel& p) const
{
return n<p.n;
}
Pixel Pixel::inv() const Pixel Pixel::inv() const
{ {
uint8_t nR = uint8_t(std::min(255, std::max(0, 255 - int(r)))); uint8_t nR = uint8_t(std::min(255, std::max(0, 255 - int(r))));

@ -87,6 +87,7 @@ namespace olc{
Pixel& operator -=(const Pixel& p); Pixel& operator -=(const Pixel& p);
Pixel operator * (const Pixel& p) const; Pixel operator * (const Pixel& p) const;
Pixel& operator *=(const Pixel& p); Pixel& operator *=(const Pixel& p);
bool operator < (const Pixel& p)const;
Pixel inv() const; Pixel inv() const;
}; };

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 3 #define VERSION_PATCH 3
#define VERSION_BUILD 10424 #define VERSION_BUILD 10443
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -117,6 +117,7 @@ Images
GFX_PurpleEnergyBallHit = purpleenergyball_hit.png GFX_PurpleEnergyBallHit = purpleenergyball_hit.png
GFX_PoisonPool = poison_pool.png GFX_PoisonPool = poison_pool.png
GFX_PoisonBottle = poison_bottle.png GFX_PoisonBottle = poison_bottle.png
GFX_Fragment = items/Fragment.png
GFX_Thief_Sheet = nico-thief.png GFX_Thief_Sheet = nico-thief.png
GFX_Trapper_Sheet = nico-trapper.png GFX_Trapper_Sheet = nico-trapper.png

@ -1,3 +1,5 @@
Fragment Description = "A small piece of concentrated material from broken down jewelry."
Equipment Equipment
{ {
Ring of the Slime King Ring of the Slime King
@ -5,6 +7,10 @@ Equipment
Slot = Ring1,Ring2 Slot = Ring1,Ring2
ItemCategory = Accessories 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 # See ItemStats.txt for valid stat names
StatValues = Health,Mana,Move Spd % StatValues = Health,Mana,Move Spd %
MinStats = 5,1,1 MinStats = 5,1,1
@ -18,6 +24,8 @@ Equipment
Slot = Ring1,Ring2 Slot = Ring1,Ring2
ItemCategory = Accessories ItemCategory = Accessories
Fragment Name = Bear Ring Fragment
# See ItemStats.txt for valid stat names # See ItemStats.txt for valid stat names
StatValues = Health,Attack,Mana StatValues = Health,Attack,Mana
MinStats = 4,1,1 MinStats = 4,1,1
@ -31,6 +39,8 @@ Equipment
Slot = Ring1,Ring2 Slot = Ring1,Ring2
ItemCategory = Accessories ItemCategory = Accessories
Fragment Name = Stone Ring Fragment
# See ItemStats.txt for valid stat names # See ItemStats.txt for valid stat names
StatValues = Defense,Health,Health % StatValues = Defense,Health,Health %
MinStats = 5,10,1 MinStats = 5,10,1
@ -44,6 +54,8 @@ Equipment
Slot = Ring1,Ring2 Slot = Ring1,Ring2
ItemCategory = Accessories ItemCategory = Accessories
Fragment Name = Bird's Treasure Fragment
# See ItemStats.txt for valid stat names # See ItemStats.txt for valid stat names
StatValues = Move Spd %,Crit Rate,Mana StatValues = Move Spd %,Crit Rate,Mana
MinStats = 1,1,2 MinStats = 1,1,2

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Loading…
Cancel
Save