Add unequip hotkey to character equipment menu. Implemented mouse inputs displaying on input helper when mouse navigation is used. Release Build 7465.
This commit is contained in:
parent
e2cc0aa90c
commit
63f7062841
@ -136,6 +136,7 @@ InputGroup AiL::KEY_SCROLLVERT_L;
|
||||
InputGroup AiL::KEY_SCROLL;
|
||||
InputGroup AiL::KEY_SHOULDER;
|
||||
InputGroup AiL::KEY_CHANGE_LOADOUT;
|
||||
InputGroup AiL::KEY_MOUSE_RIGHT;
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
::discord::Core*Discord{};
|
||||
@ -2607,6 +2608,8 @@ void AiL::InitializeDefaultKeybinds(){
|
||||
KEY_UNEQUIP.AddKeybind({KEY,R});
|
||||
KEY_UNEQUIP.AddKeybind({CONTROLLER,static_cast<int>(GPButtons::FACE_U)});
|
||||
|
||||
KEY_MOUSE_RIGHT.AddKeybind({MOUSE,Mouse::RIGHT});
|
||||
|
||||
#define TieMenuNameToMenuInputGroup(KEY_NAME) \
|
||||
InputGroup::menuNamesToInputGroups[DATA["Inputs"][#KEY_NAME].GetString()]=&KEY_NAME; \
|
||||
InputGroup::menuInputGroups.push_back(DATA["Inputs"][#KEY_NAME].GetString());
|
||||
|
@ -108,6 +108,8 @@ public:
|
||||
static InputGroup KEY_CHANGE_LOADOUT;
|
||||
static InputGroup KEY_ENTER;
|
||||
|
||||
static InputGroup KEY_MOUSE_RIGHT;
|
||||
|
||||
static float SIZE_CHANGE_SPEED;
|
||||
double levelTime;
|
||||
Camera2D camera;
|
||||
|
@ -305,7 +305,7 @@ void Menu::InitializeCharacterMenuWindow(){
|
||||
yOffset+=20;
|
||||
}
|
||||
|
||||
characterMenuWindow->ADD("Back button",MenuComponent)(geom2d::rect<float>{{windowSize.x/2-64,windowSize.y},{128,12}},"Back",[](MenuFuncData data){Menu::stack.pop_back();return true;})END;
|
||||
characterMenuWindow->ADD("Back button",MenuComponent)(geom2d::rect<float>{{windowSize.x/2-64,windowSize.y-4.f},{128,12}},"Back",[](MenuFuncData data){Menu::stack.pop_back();return true;})END;
|
||||
|
||||
auto itemNameDisplay=characterMenuWindow->ADD("Item Name",MenuLabel)(geom2d::rect<float>{{0,28},{120,12}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW|ComponentAttr::FIT_TO_LABEL)END;
|
||||
auto itemDescriptionDisplay=characterMenuWindow->ADD("Item Description",MenuLabel)(geom2d::rect<float>{{0,40},{120,windowSize.y-49}},"",1,ComponentAttr::BACKGROUND|ComponentAttr::LEFT_ALIGN|ComponentAttr::OUTLINE|ComponentAttr::SHADOW)END;
|
||||
@ -324,6 +324,40 @@ void Menu::InitializeCharacterMenuWindow(){
|
||||
{ //Button Key
|
||||
{{game->KEY_SHOULDER,Pressed},{"Scroll",[](MenuType type){}}},
|
||||
{{game->KEY_SCROLL,Analog},{"Scroll",[](MenuType type){}}},
|
||||
{{game->KEY_MOUSE_RIGHT,Pressed},{[](MenuFuncData data){
|
||||
if(!data.menu.GetSelection().expired()&&
|
||||
data.menu.GetSelection().lock()->GetName().starts_with("Equip Slot ")){
|
||||
if(!ISBLANK(Inventory::GetEquip(EquipSlot(data.menu.GetSelection().lock()->I(Attribute::EQUIP_TYPE))))){
|
||||
return "Unequip";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},[](MenuType type){
|
||||
if(!Menu::menus[type]->GetSelection().expired()&&
|
||||
Menu::menus[type]->GetSelection().lock()->GetName().starts_with("Equip Slot ")){
|
||||
if(!ISBLANK(Inventory::GetEquip(EquipSlot(Menu::menus[type]->GetSelection().lock()->I(Attribute::EQUIP_TYPE))))){
|
||||
Inventory::UnequipItem(EquipSlot(Menu::menus[type]->GetSelection().lock()->I(Attribute::EQUIP_TYPE)));
|
||||
SoundEffect::PlaySFX("Unequip Armor",SoundEffect::CENTERED);
|
||||
}
|
||||
}
|
||||
}}},
|
||||
{{game->KEY_FACELEFT,Pressed},{[](MenuFuncData data){
|
||||
if(!data.menu.GetSelection().expired()&&
|
||||
data.menu.GetSelection().lock()->GetName().starts_with("Equip Slot ")){
|
||||
if(!ISBLANK(Inventory::GetEquip(EquipSlot(data.menu.GetSelection().lock()->I(Attribute::EQUIP_TYPE))))){
|
||||
return "Unequip";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},[](MenuType type){
|
||||
if(!Menu::menus[type]->GetSelection().expired()&&
|
||||
Menu::menus[type]->GetSelection().lock()->GetName().starts_with("Equip Slot ")){
|
||||
if(!ISBLANK(Inventory::GetEquip(EquipSlot(Menu::menus[type]->GetSelection().lock()->I(Attribute::EQUIP_TYPE))))){
|
||||
Inventory::UnequipItem(EquipSlot(Menu::menus[type]->GetSelection().lock()->I(Attribute::EQUIP_TYPE)));
|
||||
SoundEffect::PlaySFX("Unequip Armor",SoundEffect::CENTERED);
|
||||
}
|
||||
}
|
||||
}}},
|
||||
{game->KEY_BACK,{"Back",[](MenuType type){
|
||||
if(!Menu::menus[type]->GetSelection().expired()&&
|
||||
!Menu::menus[type]->GetSelection().lock()->parentComponent.expired()&&
|
||||
|
@ -49,17 +49,7 @@ InputHelper::InputHelper(){}
|
||||
|
||||
void InputHelper::Initialize(MenuInputGroups&inputGroups){
|
||||
this->inputGroups.clear();
|
||||
for(auto&data:inputGroups){
|
||||
if(data.first.GetLabelVisible()){ //If the label is not visible, we don't care to include it in our list.
|
||||
if(std::holds_alternative<ButtonName>(data.second.first)){
|
||||
const ButtonName&name=std::get<ButtonName>(data.second.first);
|
||||
groupedInputs[name].push_back(data.first.GetGroup());
|
||||
|
||||
if(groupedInputs[name].size()>1)continue; //Skip adding to the list of input groups because this input already has been added.
|
||||
}
|
||||
this->inputGroups[data.first.GetGroup()]=data.second.first;
|
||||
}
|
||||
}
|
||||
groupData=inputGroups;
|
||||
}
|
||||
|
||||
const InputType InputHelper::InputMode()const{
|
||||
@ -79,32 +69,73 @@ void InputHelper::Draw(){
|
||||
std::vector<std::vector<std::variant<Decal*,std::string>>>buttonImgs; //Store decals for buttons that actually have images, and strings for buttons that have labels. One button can have multiple icons. Store them all together.
|
||||
std::vector<std::string>buttonDescriptions;
|
||||
#pragma region Populate all buttons to display
|
||||
inputGroups.clear();
|
||||
groupedInputs.clear();
|
||||
for(auto&data:groupData){
|
||||
if(data.first.GetLabelVisible()){ //If the label is not visible, we don't care to include it in our list.
|
||||
if(std::holds_alternative<ButtonName>(data.second.first)){
|
||||
const ButtonName&name=std::get<ButtonName>(data.second.first);
|
||||
groupedInputs[name].push_back(data.first.GetGroup());
|
||||
|
||||
if(groupedInputs[name].size()>1)continue; //Skip adding to the list of input groups because this input already has been added.
|
||||
}else
|
||||
if(std::holds_alternative<std::function<std::string(MenuFuncData)>>(data.second.first)){
|
||||
std::weak_ptr<ScrollableWindowComponent>parentComponent;
|
||||
if(!Menu::stack.back()->GetSelection().expired()){
|
||||
parentComponent=Menu::stack.back()->GetSelection().lock()->parentComponent;
|
||||
}
|
||||
std::string name=std::get<std::function<std::string(MenuFuncData)>>(data.second.first)(MenuFuncData{*Menu::stack.back(),game,Menu::stack.back()->GetSelection(),parentComponent});
|
||||
groupedInputs[name].push_back(data.first.GetGroup());
|
||||
|
||||
if(groupedInputs[name].size()>1)continue; //Skip adding to the list of input groups because this input already has been added.
|
||||
}
|
||||
this->inputGroups[data.first.GetGroup()]=data.second.first;
|
||||
}
|
||||
}
|
||||
for(auto&[group,display]:inputGroups){
|
||||
size_t groupedInputCount=1;
|
||||
std::vector<InputGroup>inputGroupsToCheck;
|
||||
if(std::holds_alternative<std::string>(display)&&groupedInputs.count(std::get<std::string>(display))){
|
||||
inputGroupsToCheck=groupedInputs.at(std::get<std::string>(display));
|
||||
}else{
|
||||
inputGroupsToCheck.push_back(group);
|
||||
std::weak_ptr<ScrollableWindowComponent>parentComponent;
|
||||
if(!Menu::stack.back()->GetSelection().expired()){
|
||||
parentComponent=Menu::stack.back()->GetSelection().lock()->parentComponent;
|
||||
}
|
||||
|
||||
std::vector<InputGroup>inputGroupsToCheck;
|
||||
std::string displayName;
|
||||
|
||||
if(std::holds_alternative<std::string>(display))displayName=std::get<std::string>(display);
|
||||
else
|
||||
if(std::holds_alternative<std::function<std::string(MenuFuncData)>>(display)){
|
||||
std::weak_ptr<ScrollableWindowComponent>parentComponent;
|
||||
if(!Menu::stack.back()->GetSelection().expired()){
|
||||
parentComponent=Menu::stack.back()->GetSelection().lock()->parentComponent;
|
||||
}
|
||||
displayName=std::get<std::function<std::string(MenuFuncData)>>(display)(MenuFuncData{*Menu::stack.back(),game,Menu::stack.back()->GetSelection(),parentComponent});
|
||||
}
|
||||
else ERR("WARNING! display contains a variant alternative that does not exist. THIS SHOULD NOT BE HAPPENING!");
|
||||
|
||||
if(groupedInputs.count(displayName)){
|
||||
inputGroupsToCheck=groupedInputs.at(displayName);
|
||||
}else{
|
||||
inputGroupsToCheck.push_back(group);
|
||||
}
|
||||
|
||||
buttonImgs.push_back({});
|
||||
std::vector<std::variant<Decal*,std::string>>&iconList=buttonImgs.back();
|
||||
|
||||
for(InputGroup&group:inputGroupsToCheck){
|
||||
if(Menu::UsingMouseNavigation()){
|
||||
auto&primaryKey=group.GetPrimaryKey(MOUSE);
|
||||
|
||||
if(displayName.length()>0&&primaryKey.has_value()){
|
||||
if(primaryKey.value().HasExtendedIcons()){//This means it follows the specialized icon controller schemes, now pick based on these icons.
|
||||
buttonImgWidth+=primaryKey.value().GetIcon(GameSettings::GetIconType()).Sprite()->width+"Interface.InputHelperSpacing"_I;
|
||||
iconList.push_back(primaryKey.value().GetIcon(GameSettings::GetIconType()).Decal());
|
||||
}else
|
||||
if(primaryKey.value().HasIcon()){
|
||||
buttonImgWidth+=primaryKey.value().GetIcon().Sprite()->width+"Interface.InputHelperSpacing"_I;
|
||||
iconList.push_back(primaryKey.value().GetIcon().Decal());
|
||||
}else{
|
||||
buttonImgWidth+=game->GetTextSizeProp(primaryKey.value().GetDisplayName()).x+"Interface.InputHelperSpacing"_I;
|
||||
iconList.push_back(primaryKey.value().GetDisplayName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto&primaryKey=group.GetPrimaryKey(mode);
|
||||
|
||||
if(displayName.length()>0&&primaryKey.has_value()){
|
||||
|
@ -46,6 +46,7 @@ All rights reserved.
|
||||
class InputHelper{
|
||||
std::map<InputGroup,InputGroupActionDisplayName>inputGroups;
|
||||
std::map<ButtonName,std::vector<InputGroup>>groupedInputs;
|
||||
MenuInputGroups groupData;
|
||||
|
||||
const InputType InputMode()const;
|
||||
|
||||
|
@ -328,40 +328,39 @@ void Menu::KeyboardButtonNavigation(AiL*game,vf2d menuPos){
|
||||
}
|
||||
}
|
||||
|
||||
if(!Menu::UsingMouseNavigation()){
|
||||
for(auto&[input,data]:inputGroups){
|
||||
if(Menu::alreadyClicked)break;
|
||||
bool activated=false;
|
||||
switch(input.GetEngageType()){
|
||||
case Released:{
|
||||
activated=input.GetGroup().Released();
|
||||
}break;
|
||||
case Pressed:{
|
||||
activated=input.GetGroup().Pressed();
|
||||
}break;
|
||||
case PressedDAS:{
|
||||
activated=input.GetGroup().PressedDAS();
|
||||
}break;
|
||||
case Held:{
|
||||
activated=input.GetGroup().Held();
|
||||
}break;
|
||||
case Analog:{
|
||||
activated=input.GetGroup().Analog()!=0.f;
|
||||
}break;
|
||||
[[unlikely]]default:ERR(std::format("WARNING! Unhandled input engage type {}! THIS SHOULD NOT BE HAPPENING!",int(input.GetEngageType())));
|
||||
}
|
||||
for(auto&[input,data]:inputGroups){
|
||||
if(Menu::alreadyClicked)break;
|
||||
bool activated=false;
|
||||
switch(input.GetEngageType()){
|
||||
case Released:{
|
||||
activated=input.GetGroup().Released();
|
||||
}break;
|
||||
case Pressed:{
|
||||
activated=input.GetGroup().Pressed();
|
||||
}break;
|
||||
case PressedDAS:{
|
||||
activated=input.GetGroup().PressedDAS();
|
||||
}break;
|
||||
case Held:{
|
||||
activated=input.GetGroup().Held();
|
||||
}break;
|
||||
case Analog:{
|
||||
activated=input.GetGroup().Analog()!=0.f;
|
||||
}break;
|
||||
[[unlikely]]default:ERR(std::format("WARNING! Unhandled input engage type {}! THIS SHOULD NOT BE HAPPENING!",int(input.GetEngageType())));
|
||||
}
|
||||
|
||||
if(activated){
|
||||
auto&action=data.second;
|
||||
if(std::holds_alternative<ButtonName>(action))Component<MenuComponent>(type,std::get<ButtonName>(action))->Click();
|
||||
else
|
||||
if(std::holds_alternative<std::function<void(MenuType)>>(action))std::get<std::function<void(MenuType)>>(action)(type);
|
||||
else{
|
||||
ERR("WARNING! Navigation data has an unrecognized type or is empty! This should not be happening!")
|
||||
}
|
||||
if(activated){
|
||||
auto&action=data.second;
|
||||
if(std::holds_alternative<ButtonName>(action))Component<MenuComponent>(type,std::get<ButtonName>(action))->Click();
|
||||
else
|
||||
if(std::holds_alternative<std::function<void(MenuType)>>(action))std::get<std::function<void(MenuType)>>(action)(type);
|
||||
else{
|
||||
ERR("WARNING! Navigation data has an unrecognized type or is empty! This should not be happening!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!selection.expired()){
|
||||
const int MAX_ITERATIONS=10; //Skip a maximum amount of items in case everything gets disabled somehow, prevents an infinite loop.
|
||||
int iterationCount=0;
|
||||
|
@ -145,7 +145,7 @@ bool Monster::_SetX(float x,const bool monsterInvoked){
|
||||
vf2d newPos={x,pos.y};
|
||||
vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth;
|
||||
geom2d::rect<float>collisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel);
|
||||
if(isBoss||collisionRect==game->NO_COLLISION){
|
||||
if(collisionRect==game->NO_COLLISION){
|
||||
pos.x=std::clamp(x,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().width*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult()));
|
||||
Moved();
|
||||
return true;
|
||||
@ -175,7 +175,7 @@ bool Monster::_SetY(float y,const bool monsterInvoked){
|
||||
vf2d newPos={pos.x,y};
|
||||
vi2d tilePos=vi2d(newPos/float(game->GetCurrentMapData().tilewidth))*game->GetCurrentMapData().tilewidth;
|
||||
geom2d::rect<float>collisionRect=game->GetTileCollision(game->GetCurrentLevel(),newPos,upperLevel);
|
||||
if(isBoss||collisionRect==game->NO_COLLISION){
|
||||
if(collisionRect==game->NO_COLLISION){
|
||||
pos.y=std::clamp(y,game->GetCurrentMapData().tilewidth/2.f*GetSizeMult(),float(game->GetCurrentMapData().height*game->GetCurrentMapData().tilewidth-game->GetCurrentMapData().tilewidth/2.f*GetSizeMult()));
|
||||
Moved();
|
||||
return true;
|
||||
|
@ -1,7 +1,5 @@
|
||||
January 1st
|
||||
===========
|
||||
- Clamp bosses in boss arenas.
|
||||
|
||||
- Track items used during a stage, on death, restore the loadout item quantities used.
|
||||
|
||||
Add Bonus XP when completing a stage
|
||||
@ -23,4 +21,6 @@ January 31st
|
||||
|
||||
- Auto aim causes retreat-type moves to aim away from the auto target, and prefer the direction the player's moving in.
|
||||
|
||||
- Condense stage track (loading times)
|
||||
- Condense stage track (loading times)
|
||||
|
||||
- Credits/Licensing
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 7447
|
||||
#define VERSION_BUILD 7465
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -191,6 +191,11 @@ Events
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = toggle_off.ogg, 100%
|
||||
}
|
||||
Unequip Armor
|
||||
{
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
File[0] = equip2.ogg, 60%
|
||||
}
|
||||
Ursule Dead
|
||||
{
|
||||
# Specify file names, followed by volume %. Optional min and max pitch adjustment (Defaults are 90%,110%)
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user