Character Info Window layouts setup

pull/28/head
sigonasr2 1 year ago
parent 298b0c4ca7
commit a659bf7924
  1. 33
      Crawler/AttributableStat.h
  2. 14
      Crawler/BitwiseEnum.h
  3. 72
      Crawler/CharacterMenuWindow.cpp
  4. 4
      Crawler/Crawler.cpp
  5. 2
      Crawler/Item.cpp
  6. 2
      Crawler/MenuComponent.h
  7. 4
      Crawler/MenuItemItemButton.h
  8. 20
      Crawler/Player.cpp
  9. 7
      Crawler/Player.h
  10. 15
      Crawler/PopupMenuLabel.h
  11. 8
      Crawler/ScrollableWindowComponent.h
  12. 2
      Crawler/Version.h

@ -45,7 +45,7 @@ enum class ItemAttribute{
/*////////////////////////////////////////////*/ /*////////////////////////////////////////////*/
/*//////*/ENUM_START,/*///////////////////////*/ /*//////*/ENUM_START,/*///////////////////////*/
/*////////////////////////////////////////////*/ /*////////////////////////////////////////////*/
//////////////
defense, defense,
health, health,
attack, attack,
@ -56,18 +56,49 @@ enum class ItemAttribute{
healthPct, //Percentage of health boost healthPct, //Percentage of health boost
healthPctRecoveryPer6sec, //Percentage of health recovered every 6 seconds. healthPctRecoveryPer6sec, //Percentage of health recovered every 6 seconds.
/////////NOTE: When adding a new item stat, provide its display name in the map below.
/*////////////////////////////////////////////*/ /*////////////////////////////////////////////*/
/*//////*/ENUM_END/*//////////////////////////*/ /*//////*/ENUM_END/*//////////////////////////*/
/*////////////////////////////////////////////*/ /*////////////////////////////////////////////*/
}; };
namespace DisplayType{
enum DisplayType{
DISPLAY_AS_NUMBER=0,
DISPLAY_AS_PERCENT=1,
};
}
struct AttributeData{
std::string name;
DisplayType::DisplayType displayAsPercent;
};
class ItemAttributable{ class ItemAttributable{
std::map<ItemAttribute,int>attributes; std::map<ItemAttribute,int>attributes;
private:
inline static std::map<ItemAttribute,AttributeData>data{
{ItemAttribute::defense,{"Defense",DisplayType::DISPLAY_AS_NUMBER}},
{ItemAttribute::health,{"Health",DisplayType::DISPLAY_AS_NUMBER}},
{ItemAttribute::attack,{"Attack",DisplayType::DISPLAY_AS_NUMBER}},
{ItemAttribute::moveSpdPct,{"Move Spd",DisplayType::DISPLAY_AS_PERCENT}},
{ItemAttribute::cdrPct,{"CDR",DisplayType::DISPLAY_AS_PERCENT}},
{ItemAttribute::critPct,{"Crit Rate",DisplayType::DISPLAY_AS_PERCENT}},
{ItemAttribute::critDmgPct,{"Crit Dmg",DisplayType::DISPLAY_AS_PERCENT}},
{ItemAttribute::healthPct,{"Health %",DisplayType::DISPLAY_AS_PERCENT}}, //Percentage of health boost
{ItemAttribute::healthPctRecoveryPer6sec,{"HP Recovery",DisplayType::DISPLAY_AS_NUMBER}} //Percentage of health recovered every 6 seconds.}
};
public: public:
//Returns a copy of all the attributes to be passed to a new instance easily / to sync values between both.
inline void copyTo(ItemAttributable&target){
target.attributes=attributes;
}
inline int&get(ItemAttribute a){ inline int&get(ItemAttribute a){
return attributes[a]; return attributes[a];
} }
inline const int get_readOnly(ItemAttribute a)const{ inline const int get_readOnly(ItemAttribute a)const{
return attributes.at(a); return attributes.at(a);
} }
inline static AttributeData GetDisplayInfo(ItemAttribute a){
return data[a];
}
}; };

@ -47,4 +47,18 @@ template<typename T>
constexpr auto operator&(T attribute,T attribute2) noexcept constexpr auto operator&(T attribute,T attribute2) noexcept
{ {
return static_cast<std::underlying_type_t<T>>(attribute)&static_cast<std::underlying_type_t<T>>(attribute2); return static_cast<std::underlying_type_t<T>>(attribute)&static_cast<std::underlying_type_t<T>>(attribute2);
}
template<typename T>
constexpr auto operator|=(T&lhs,const T&rhs) noexcept
{
lhs=T(static_cast<std::underlying_type_t<T>>(lhs)|static_cast<std::underlying_type_t<T>>(rhs));
return lhs;
}
template<typename T>
constexpr auto operator&=(T&lhs,const T&rhs) noexcept
{
lhs=T(static_cast<std::underlying_type_t<T>>(lhs)&static_cast<std::underlying_type_t<T>>(rhs));
return lhs;
} }

@ -41,6 +41,10 @@ All rights reserved.
#include "CharacterRotatingDisplay.h" #include "CharacterRotatingDisplay.h"
#include "Crawler.h" #include "Crawler.h"
#include "ClassInfo.h" #include "ClassInfo.h"
#include "MenuItemItemButton.h"
#include "Item.h"
#include "PopupMenuLabel.h"
#include "ScrollableWindowComponent.h"
INCLUDE_game INCLUDE_game
INCLUDE_GFX INCLUDE_GFX
@ -57,4 +61,72 @@ void Menu::InitializeCharacterMenuWindow(){
characterMenuWindow->AddComponent("Character Label",characterLabel); characterMenuWindow->AddComponent("Character Label",characterLabel);
characterMenuWindow->AddComponent("Equip Slot Outline",equipSlotOutline); characterMenuWindow->AddComponent("Equip Slot Outline",equipSlotOutline);
characterMenuWindow->AddComponent("Character Rotating Display",charDisplay); characterMenuWindow->AddComponent("Character Rotating Display",charDisplay);
MenuComponent*equipSelectionOutline=NEW MenuComponent(CHARACTER_MENU,{{123,36},{120,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE);
ScrollableWindowComponent*equipmentList=NEW ScrollableWindowComponent(CHARACTER_MENU,{{123,36},{120,windowSize.y-37-24}});
MenuComponent*equipSelectionBottomOutline=NEW MenuComponent(CHARACTER_MENU,{{123,36+(windowSize.y-37-24)},{120,24}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE);
MenuComponent*equipSelectionSelectButton=NEW MenuComponent(CHARACTER_MENU,{{123+12,36+(windowSize.y-37-24)+6},{96,12}},"Select",DO_NOTHING);
equipSelectionOutline->Enable(false);
equipmentList->Enable(false);
equipSelectionBottomOutline->Enable(false);
equipSelectionSelectButton->Enable(false);
characterMenuWindow->AddComponent("Equip Selection Outline",equipSelectionOutline);
characterMenuWindow->AddComponent("Equip List",equipmentList);
characterMenuWindow->AddComponent("Equip Selection Bottom Outline",equipSelectionBottomOutline);
characterMenuWindow->AddComponent("Equip Selection Select Button",equipSelectionSelectButton);
int equipSlot=1;
for(int i=0;i<8;i++){
float x=31+(i%2)*33;
float y=24+(i/2)*28;
float labelX=2+(i%2)*90;
float labelY=24+(i/2)*28+36;
if(i<6){
y-=8;
labelY-=8;
}
const std::array<std::string,8>slotNames{"Helmet","Weapon","Armor","Gloves","Pants","Shoes","Ring 1","Ring 2"};
EquipSlot slot=EquipSlot(equipSlot);
MenuItemItemButton*equipmentSlot=NEW MenuItemItemButton(CHARACTER_MENU,{{x,y+36},{24,24}},Item::BLANK,MenuType::ENUM_END,
[](MenuFuncData data){
Component<MenuComponent>(data.component->parentMenu,"Equip Selection Outline")->Enable(true);
Component<ScrollableWindowComponent>(data.component->parentMenu,"Equip List")->Enable(true);
Component<MenuComponent>(data.component->parentMenu,"Equip Selection Bottom Outline")->Enable(true);
Component<MenuComponent>(data.component->parentMenu,"Equip Selection Select Button")->Enable(true);
Component<CharacterRotatingDisplay>(data.component->parentMenu,"Character Rotating Display")->Enable(false);
return true;
},MenuType::ENUM_END,"","");
PopupMenuLabel*equipmentLabel=NEW PopupMenuLabel(CHARACTER_MENU,{{labelX,labelY},{29,24}},slotNames[i],{0.5,1},ComponentAttr::SHADOW);
equipSlot<<=1;
characterMenuWindow->AddComponent("Equip Slot "+slotNames[i],equipmentSlot);
characterMenuWindow->AddComponent("Equip Label "+slotNames[i],equipmentLabel);
}
MenuComponent*statDisplayOutline=NEW MenuComponent(CHARACTER_MENU,{{245,36},{62,windowSize.y-37}},"",DO_NOTHING,ButtonAttr::UNSELECTABLE);
const std::array<ItemAttribute,7>displayAttrs{
ItemAttribute::health,
ItemAttribute::attack,
ItemAttribute::defense,
ItemAttribute::moveSpdPct,
ItemAttribute::cdrPct,
ItemAttribute::critPct,
ItemAttribute::critDmgPct,
};
characterMenuWindow->AddComponent("Stat Display Outline",statDisplayOutline);
int yOffset=0;
for(ItemAttribute attribute:displayAttrs){
AttributeData data=ItemAttributable::GetDisplayInfo(attribute);
std::string attrStr=data.name+":\n ";
attrStr+=std::to_string(game->GetPlayer()->A(attribute));
if(data.displayAsPercent){
attrStr+="%";
}
MenuLabel*attrLabel=NEW MenuLabel(CHARACTER_MENU,{{245,36+2+float(yOffset)},{62,18}},attrStr,1,ComponentAttr::SHADOW|ComponentAttr::LEFT_ALIGN);
yOffset+=20;
characterMenuWindow->AddComponent("Attribute "+data.name+" Label",attrLabel);
}
} }

@ -1702,8 +1702,8 @@ void Crawler::ChangePlayerClass(Class cl){
player.reset(NEW Witch(player.get())); player.reset(NEW Witch(player.get()));
}break; }break;
} }
player->hp=player->maxhp=DATA.GetProperty(player->GetClassName()+".BaseHealth").GetInt(); player->hp=player->A(ItemAttribute::health)=DATA.GetProperty(player->GetClassName()+".BaseHealth").GetInt();
player->atk=DATA.GetProperty(player->GetClassName()+".BaseAtk").GetInt(); player->A(ItemAttribute::attack)=DATA.GetProperty(player->GetClassName()+".BaseAtk").GetInt();
player->hpGrowthRate=float(DATA.GetProperty(player->GetClassName()+".HealthGrowthRate").GetReal()); player->hpGrowthRate=float(DATA.GetProperty(player->GetClassName()+".HealthGrowthRate").GetReal());
player->atkGrowthRate=float(DATA.GetProperty(player->GetClassName()+".AtkGrowthRate").GetReal()); player->atkGrowthRate=float(DATA.GetProperty(player->GetClassName()+".AtkGrowthRate").GetReal());
sig::Animation::SetupPlayerAnimations(); sig::Animation::SetupPlayerAnimations();

@ -131,7 +131,7 @@ void ItemInfo::InitializeItems(){
if(slot.size()>0){ if(slot.size()>0){
for(std::string&s:slot){ for(std::string&s:slot){
if(!nameToEquipSlot.count(s))ERR("WARNING! Tried to add item "<<it.name<<" to slot "<<s<<" which doesn't exist!"); if(!nameToEquipSlot.count(s))ERR("WARNING! Tried to add item "<<it.name<<" to slot "<<s<<" which doesn't exist!");
it.slot=it.slot|nameToEquipSlot[s]; it.slot|=nameToEquipSlot[s];
} }
} }
if(!ITEM_CATEGORIES.count(it.category)){ if(!ITEM_CATEGORIES.count(it.category)){

@ -109,6 +109,6 @@ public:
virtual void OnInventorySlotsUpdate(ITCategory cat); virtual void OnInventorySlotsUpdate(ITCategory cat);
std::string GetLabel(); std::string GetLabel();
std::string GetName(); std::string GetName();
void Enable(bool enabled); virtual void Enable(bool enabled);
virtual void Cleanup(); virtual void Cleanup();
}; };

@ -67,13 +67,13 @@ protected:
valid=!itemRef.IsBlank(); valid=!itemRef.IsBlank();
if(valid){ if(valid){
icon=itemRef.Decal(); icon=itemRef.Decal();
if(hovered){ if(hovered&&itemDescriptionMenu!=MenuType::ENUM_END){
Component<MenuLabel>(itemDescriptionMenu,itemNameLabelName)->label=itemRef.Name(); Component<MenuLabel>(itemDescriptionMenu,itemNameLabelName)->label=itemRef.Name();
Component<MenuLabel>(itemDescriptionMenu,itemDescriptionLabelName)->label=itemRef.Description(); Component<MenuLabel>(itemDescriptionMenu,itemDescriptionLabelName)->label=itemRef.Description();
} }
}else{ }else{
icon=nullptr; icon=nullptr;
if(hovered){ if(hovered&&itemDescriptionMenu!=MenuType::ENUM_END){
Component<MenuLabel>(itemDescriptionMenu,itemNameLabelName)->label=""; Component<MenuLabel>(itemDescriptionMenu,itemNameLabelName)->label="";
Component<MenuLabel>(itemDescriptionMenu,itemDescriptionLabelName)->label=""; Component<MenuLabel>(itemDescriptionMenu,itemDescriptionLabelName)->label="";
} }

@ -76,11 +76,21 @@ Player::Player()
Player::Player(Player*player) Player::Player(Player*player)
:pos(player->GetPos()),vel(player->GetVelocity()),iframe_time(player->iframe_time),lastReleasedMovementKey(DOWN), :pos(player->GetPos()),vel(player->GetVelocity()),iframe_time(player->iframe_time),lastReleasedMovementKey(DOWN),
facingDirection(DOWN),state(State::NORMAL){ facingDirection(DOWN),state(State::NORMAL){
player->copyTo(*this);
Initialize(); Initialize();
} }
void Player::Initialize(){ void Player::Initialize(){
Player::GROUND_SLAM_SPIN_TIME="Warrior.Ability 2.SpinTime"_F; Player::GROUND_SLAM_SPIN_TIME="Warrior.Ability 2.SpinTime"_F;
A(ItemAttribute::health)=hp;
A(ItemAttribute::defense)=0;
A(ItemAttribute::attack)="Warrior.BaseAtk"_I;
A(ItemAttribute::moveSpdPct)=100;
A(ItemAttribute::cdrPct)=0;
A(ItemAttribute::critPct)=0;
A(ItemAttribute::critDmgPct)=0;
A(ItemAttribute::healthPct)=0;
A(ItemAttribute::healthPctRecoveryPer6sec)=0;
} }
bool Player::SetX(float x){ bool Player::SetX(float x){
@ -169,7 +179,7 @@ int Player::GetHealth(){
} }
int Player::GetMaxHealth(){ int Player::GetMaxHealth(){
return maxhp; return A(ItemAttribute::health);
} }
int Player::GetMana(){ int Player::GetMana(){
@ -181,15 +191,15 @@ int Player::GetMaxMana() {
} }
int Player::GetAttack(){ int Player::GetAttack(){
float mod_atk=float(atk); float mod_atk=float(A(ItemAttribute::attack));
for(Buff&b:GetBuffs(BuffType::ATTACK_UP)){ for(Buff&b:GetBuffs(BuffType::ATTACK_UP)){
mod_atk+=atk*b.intensity; mod_atk+=A(ItemAttribute::attack)*b.intensity;
} }
return int(mod_atk); return int(mod_atk);
} }
float Player::GetMoveSpdMult(){ float Player::GetMoveSpdMult(){
float mod_moveSpd=moveSpd; float mod_moveSpd=A(ItemAttribute::moveSpdPct)/100.f;
for(Buff&b:GetBuffs(BuffType::SLOWDOWN)){ for(Buff&b:GetBuffs(BuffType::SLOWDOWN)){
mod_moveSpd-=mod_moveSpd*b.intensity; mod_moveSpd-=mod_moveSpd*b.intensity;
} }
@ -779,7 +789,7 @@ void Player::SetIframes(float duration){
} }
bool Player::Heal(int damage){ bool Player::Heal(int damage){
hp=std::clamp(hp+damage,0,maxhp); hp=std::clamp(hp+damage,0,A(ItemAttribute::health));
if(damage>0){ if(damage>0){
DAMAGENUMBER_LIST.push_back(std::make_shared<DamageNumber>(GetPos(),damage,true,HEALTH_GAIN)); DAMAGENUMBER_LIST.push_back(std::make_shared<DamageNumber>(GetPos(),damage,true,HEALTH_GAIN));
} }

@ -47,6 +47,7 @@ All rights reserved.
#include "Key.h" #include "Key.h"
#include "Class.h" #include "Class.h"
#include "Item.h" #include "Item.h"
#include "AttributableStat.h"
#undef GetClassName #undef GetClassName
struct DamageNumber; struct DamageNumber;
@ -58,7 +59,7 @@ struct CastInfo{
vf2d castPos; vf2d castPos;
}; };
struct Player{ struct Player:ItemAttributable{
friend class Crawler; friend class Crawler;
friend class sig::Animation; friend class sig::Animation;
friend struct Warrior; friend struct Warrior;
@ -69,14 +70,12 @@ struct Player{
friend struct Witch; friend struct Witch;
friend class State_GameRun; friend class State_GameRun;
private: private:
int hp="Warrior.BaseHealth"_I,maxhp=hp; int hp="Warrior.BaseHealth"_I;
int mana="Player.BaseMana"_I,maxmana=mana; int mana="Player.BaseMana"_I,maxmana=mana;
int atk="Warrior.BaseAtk"_I;
float hpGrowthRate="Warrior.HealthGrowthRate"_F; float hpGrowthRate="Warrior.HealthGrowthRate"_F;
float atkGrowthRate="Warrior.AtkGrowthRate"_F; float atkGrowthRate="Warrior.AtkGrowthRate"_F;
vf2d pos; vf2d pos;
float z=0; float z=0;
float moveSpd=1.0f;
float size=1.0f; float size=1.0f;
float spin_attack_timer=0; float spin_attack_timer=0;
float spin_spd=0; float spin_spd=0;

@ -45,10 +45,13 @@ INCLUDE_game
class PopupMenuLabel:public MenuLabel{ class PopupMenuLabel:public MenuLabel{
private: private:
float scale; vf2d scale;
public: public:
inline PopupMenuLabel(MenuType parent,geom2d::rect<float>rect,std::string label,float scale=1,ComponentAttr attributes=ComponentAttr::NONE) inline PopupMenuLabel(MenuType parent,geom2d::rect<float>rect,std::string label,float scale=1,ComponentAttr attributes=ComponentAttr::NONE)
:MenuLabel(parent,rect,label,int(scale),attributes),scale(scale){ :MenuLabel(parent,rect,label,1,attributes),scale({scale,scale}){
}
inline PopupMenuLabel(MenuType parent,geom2d::rect<float>rect,std::string label,vf2d scale={1,1},ComponentAttr attributes=ComponentAttr::NONE)
:MenuLabel(parent,rect,label,1,attributes),scale(scale){
} }
protected: protected:
virtual void inline Update(Crawler*game)override{ virtual void inline Update(Crawler*game)override{
@ -58,8 +61,8 @@ protected:
virtual void inline DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{ virtual void inline DrawDecal(Crawler*game,vf2d parentPos,bool focused)override{
if(label.length()>0){ if(label.length()>0){
MenuLabel::DrawDecal(game,parentPos,focused); MenuLabel::DrawDecal(game,parentPos,focused);
std::string wrappedText=util::WrapText(game,label,int(rect.size.x-1),true,{scale,scale}); std::string wrappedText=util::WrapText(game,label,int(rect.size.x-1),true,scale);
vf2d drawPos=Menu::menus.at(parentMenu)->pos+parentPos+rect.middle()-vf2d{game->GetTextSizeProp(wrappedText)}*float(scale)/2; //Assume centered. vf2d drawPos=Menu::menus.at(parentMenu)->pos+parentPos+rect.middle()-vf2d{game->GetTextSizeProp(wrappedText)}*scale/2; //Assume centered.
if(!centered){ if(!centered){
drawPos=Menu::menus.at(parentMenu)->pos+vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(wrappedText).y/2}+parentPos; //We should at least vertically align here. drawPos=Menu::menus.at(parentMenu)->pos+vf2d{rect.pos.x+2,rect.middle().y-game->GetTextSizeProp(wrappedText).y/2}+parentPos; //We should at least vertically align here.
} }
@ -73,9 +76,9 @@ protected:
game->DrawStringPropDecal(Menu::menus.at(parentMenu)->pos+rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2,label); game->DrawStringPropDecal(Menu::menus.at(parentMenu)->pos+rect.pos+parentPos+rect.size/2-game->GetTextSizeProp(label)/2,label);
} }
if(shadow){ if(shadow){
game->DrawShadowStringPropDecal(drawPos,wrappedText,WHITE,BLACK,{scale,scale}); game->DrawShadowStringPropDecal(drawPos,wrappedText,WHITE,BLACK,scale);
}else{ }else{
game->DrawStringPropDecal(drawPos,wrappedText,WHITE,{scale,scale}); game->DrawStringPropDecal(drawPos,wrappedText,WHITE,scale);
} }
} }
} }

@ -64,9 +64,6 @@ public:
background=attributes&ComponentAttr::BACKGROUND; background=attributes&ComponentAttr::BACKGROUND;
border=attributes&ComponentAttr::OUTLINE; border=attributes&ComponentAttr::OUTLINE;
r.Create(uint32_t(rect.size.x),uint32_t(rect.size.y)); r.Create(uint32_t(rect.size.x),uint32_t(rect.size.y));
}
protected:
virtual inline void AfterCreate()override{
upButton=NEW MenuComponent(parentMenu,{rect.pos+vf2d{rect.size.x-12,0},{12,12}},"^",[&](MenuFuncData dat){V(A::SCROLL_OFFSET).y+="ThemeGlobal.MenuButtonScrollSpeed"_I;return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD); upButton=NEW MenuComponent(parentMenu,{rect.pos+vf2d{rect.size.x-12,0},{12,12}},"^",[&](MenuFuncData dat){V(A::SCROLL_OFFSET).y+="ThemeGlobal.MenuButtonScrollSpeed"_I;return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD);
downButton=NEW MenuComponent(parentMenu,{rect.pos+rect.size-vf2d{12,12},{12,12}},"v",[&](MenuFuncData dat){V(A::SCROLL_OFFSET).y-="ThemeGlobal.MenuButtonScrollSpeed"_I;return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD); downButton=NEW MenuComponent(parentMenu,{rect.pos+rect.size-vf2d{12,12},{12,12}},"v",[&](MenuFuncData dat){V(A::SCROLL_OFFSET).y-="ThemeGlobal.MenuButtonScrollSpeed"_I;return true;},ButtonAttr::UNSELECTABLE_VIA_KEYBOARD);
//Let's use the internal name of this component to add unique names for sub-components. //Let's use the internal name of this component to add unique names for sub-components.
@ -236,4 +233,9 @@ public:
inline std::vector<MenuComponent*>&GetComponents(){ inline std::vector<MenuComponent*>&GetComponents(){
return components; return components;
} }
virtual inline void Enable(bool enabled)override final{
disabled=!enabled;
upButton->Enable(enabled);
downButton->Enable(enabled);
};
}; };

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 1 #define VERSION_PATCH 1
#define VERSION_BUILD 3365 #define VERSION_BUILD 3441
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

Loading…
Cancel
Save