diff --git a/CMakeLists.txt b/CMakeLists.txt index 99cfe6510..0fff61f16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2462,6 +2462,7 @@ if(CLIENT) editor_trackers.cpp editor_trackers.h editor_ui.h + enums.h explanations.cpp layer_selector.cpp layer_selector.h diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 5c69cadaf..6206cea25 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -323,6 +324,8 @@ public: const CMapView *MapView() const { return &m_MapView; } CLayerSelector *LayerSelector() { return &m_LayerSelector; } + void FillGameTiles(EGameTileOp FillTile) const; + bool CanFillGameTiles() const; void AddGroup(); void AddTileLayer(); void LayerSelectImage(); diff --git a/src/game/editor/enums.h b/src/game/editor/enums.h new file mode 100644 index 000000000..d14679b95 --- /dev/null +++ b/src/game/editor/enums.h @@ -0,0 +1,36 @@ +#ifndef GAME_EDITOR_ENUMS_H +#define GAME_EDITOR_ENUMS_H + +constexpr const char *g_apGametileOpNames[] = { + "Air", + "Hookable", + "Death", + "Unhookable", + "Hookthrough", + "Freeze", + "Unfreeze", + "Deep Freeze", + "Deep Unfreeze", + "Blue Check-Tele", + "Red Check-Tele", + "Live Freeze", + "Live Unfreeze", +}; +enum class EGameTileOp +{ + AIR, + HOOKABLE, + DEATH, + UNHOOKABLE, + HOOKTHROUGH, + FREEZE, + UNFREEZE, + DEEP_FREEZE, + DEEP_UNFREEZE, + BLUE_CHECK_TELE, + RED_CHECK_TELE, + LIVE_FREEZE, + LIVE_UNFREEZE, +}; + +#endif diff --git a/src/game/editor/mapitems/layer_tiles.cpp b/src/game/editor/mapitems/layer_tiles.cpp index 380af7d8f..665a0fec9 100644 --- a/src/game/editor/mapitems/layer_tiles.cpp +++ b/src/game/editor/mapitems/layer_tiles.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -693,93 +694,126 @@ void CLayerTiles::ShowInfo() Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } -CUi::EPopupMenuFunctionResult CLayerTiles::RenderProperties(CUIRect *pToolBox) +void CLayerTiles::FillGameTiles(EGameTileOp Fill) { - CUIRect Button; - - const bool EntitiesLayer = IsEntitiesLayer(); + if(!CanFillGameTiles()) + return; std::shared_ptr pGroup = m_pEditor->m_Map.m_vpGroups[m_pEditor->m_SelectedGroup]; - // Game tiles can only be constructed if the layer is relative to the game layer - if(!EntitiesLayer && !(pGroup->m_OffsetX % 32) && !(pGroup->m_OffsetY % 32) && pGroup->m_ParallaxX == 100 && pGroup->m_ParallaxY == 100) + int Result = (int)Fill; + switch(Fill) { - pToolBox->HSplitBottom(12.0f, pToolBox, &Button); - static int s_GameTilesButton = 0; - if(m_pEditor->DoButton_Editor(&s_GameTilesButton, "Game tiles", 0, &Button, 0, "Constructs game tiles from this layer")) - m_pEditor->PopupSelectGametileOpInvoke(m_pEditor->Ui()->MouseX(), m_pEditor->Ui()->MouseY()); - const int Selected = m_pEditor->PopupSelectGameTileOpResult(); - int Result = Selected; - switch(Selected) + case EGameTileOp::HOOKTHROUGH: + Result = TILE_THROUGH_CUT; + break; + case EGameTileOp::FREEZE: + Result = TILE_FREEZE; + break; + case EGameTileOp::UNFREEZE: + Result = TILE_UNFREEZE; + break; + case EGameTileOp::DEEP_FREEZE: + Result = TILE_DFREEZE; + break; + case EGameTileOp::DEEP_UNFREEZE: + Result = TILE_DUNFREEZE; + break; + case EGameTileOp::BLUE_CHECK_TELE: + Result = TILE_TELECHECKIN; + break; + case EGameTileOp::RED_CHECK_TELE: + Result = TILE_TELECHECKINEVIL; + break; + case EGameTileOp::LIVE_FREEZE: + Result = TILE_LFREEZE; + break; + case EGameTileOp::LIVE_UNFREEZE: + Result = TILE_LUNFREEZE; + break; + default: + break; + } + if(Result > -1) + { + const int OffsetX = -pGroup->m_OffsetX / 32; + const int OffsetY = -pGroup->m_OffsetY / 32; + + std::vector> vpActions; + std::shared_ptr pGLayer = m_pEditor->m_Map.m_pGameLayer; + int GameLayerIndex = std::find(m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(), m_pEditor->m_Map.m_pGameGroup->m_vpLayers.end(), pGLayer) - m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(); + + if(Result != TILE_TELECHECKIN && Result != TILE_TELECHECKINEVIL) { - case 4: - Result = TILE_THROUGH_CUT; - break; - case 5: - Result = TILE_FREEZE; - break; - case 6: - Result = TILE_UNFREEZE; - break; - case 7: - Result = TILE_DFREEZE; - break; - case 8: - Result = TILE_DUNFREEZE; - break; - case 9: - Result = TILE_TELECHECKIN; - break; - case 10: - Result = TILE_TELECHECKINEVIL; - break; - case 11: - Result = TILE_LFREEZE; - break; - case 12: - Result = TILE_LUNFREEZE; - break; - default: - break; - } - if(Result > -1) - { - const int OffsetX = -pGroup->m_OffsetX / 32; - const int OffsetY = -pGroup->m_OffsetY / 32; - - static const char *s_apGametileOpNames[] = { - "Air", - "Hookable", - "Death", - "Unhookable", - "Hookthrough", - "Freeze", - "Unfreeze", - "Deep Freeze", - "Deep Unfreeze", - "Blue Check-Tele", - "Red Check-Tele", - "Live Freeze", - "Live Unfreeze", - }; - - std::vector> vpActions; - std::shared_ptr pGLayer = m_pEditor->m_Map.m_pGameLayer; - int GameLayerIndex = std::find(m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(), m_pEditor->m_Map.m_pGameGroup->m_vpLayers.end(), pGLayer) - m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(); - - if(Result != TILE_TELECHECKIN && Result != TILE_TELECHECKINEVIL) + if(pGLayer->m_Width < m_Width + OffsetX || pGLayer->m_Height < m_Height + OffsetY) { - if(pGLayer->m_Width < m_Width + OffsetX || pGLayer->m_Height < m_Height + OffsetY) + std::map> savedLayers; + savedLayers[LAYERTYPE_TILES] = pGLayer->Duplicate(); + savedLayers[LAYERTYPE_GAME] = savedLayers[LAYERTYPE_TILES]; + + int PrevW = pGLayer->m_Width; + int PrevH = pGLayer->m_Height; + const int NewW = pGLayer->m_Width < m_Width + OffsetX ? m_Width + OffsetX : pGLayer->m_Width; + const int NewH = pGLayer->m_Height < m_Height + OffsetY ? m_Height + OffsetY : pGLayer->m_Height; + pGLayer->Resize(NewW, NewH); + vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_WIDTH, PrevW, NewW)); + const std::shared_ptr &Action1 = std::static_pointer_cast(vpActions[vpActions.size() - 1]); + vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_HEIGHT, PrevH, NewH)); + const std::shared_ptr &Action2 = std::static_pointer_cast(vpActions[vpActions.size() - 1]); + + Action1->SetSavedLayers(savedLayers); + Action2->SetSavedLayers(savedLayers); + } + + int Changes = 0; + for(int y = OffsetY < 0 ? -OffsetY : 0; y < m_Height; y++) + { + for(int x = OffsetX < 0 ? -OffsetX : 0; x < m_Width; x++) + { + if(GetTile(x, y).m_Index) + { + const CTile ResultTile = {(unsigned char)Result}; + pGLayer->SetTile(x + OffsetX, y + OffsetY, ResultTile); + Changes++; + } + } + } + + vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup)); + char aDisplay[256]; + str_format(aDisplay, sizeof(aDisplay), "Construct '%s' game tiles (x%d)", g_apGametileOpNames[(int)Fill], Changes); + m_pEditor->m_EditorHistory.RecordAction(std::make_shared(m_pEditor, vpActions, aDisplay, true)); + } + else + { + if(!m_pEditor->m_Map.m_pTeleLayer) + { + std::shared_ptr pLayer = std::make_shared(m_pEditor, m_Width, m_Height); + m_pEditor->m_Map.MakeTeleLayer(pLayer); + m_pEditor->m_Map.m_pGameGroup->AddLayer(pLayer); + + vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, m_pEditor->m_Map.m_pGameGroup->m_vpLayers.size() - 1)); + + if(m_Width != pGLayer->m_Width || m_Height > pGLayer->m_Height) { std::map> savedLayers; savedLayers[LAYERTYPE_TILES] = pGLayer->Duplicate(); savedLayers[LAYERTYPE_GAME] = savedLayers[LAYERTYPE_TILES]; + int NewW = pGLayer->m_Width; + int NewH = pGLayer->m_Height; + if(m_Width > pGLayer->m_Width) + { + NewW = m_Width; + } + if(m_Height > pGLayer->m_Height) + { + NewH = m_Height; + } + int PrevW = pGLayer->m_Width; int PrevH = pGLayer->m_Height; - const int NewW = pGLayer->m_Width < m_Width + OffsetX ? m_Width + OffsetX : pGLayer->m_Width; - const int NewH = pGLayer->m_Height < m_Height + OffsetY ? m_Height + OffsetY : pGLayer->m_Height; - pGLayer->Resize(NewW, NewH); + pLayer->Resize(NewW, NewH); vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_WIDTH, PrevW, NewW)); const std::shared_ptr &Action1 = std::static_pointer_cast(vpActions[vpActions.size() - 1]); vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_HEIGHT, PrevH, NewH)); @@ -788,124 +822,94 @@ CUi::EPopupMenuFunctionResult CLayerTiles::RenderProperties(CUIRect *pToolBox) Action1->SetSavedLayers(savedLayers); Action2->SetSavedLayers(savedLayers); } - - int Changes = 0; - for(int y = OffsetY < 0 ? -OffsetY : 0; y < m_Height; y++) - { - for(int x = OffsetX < 0 ? -OffsetX : 0; x < m_Width; x++) - { - if(GetTile(x, y).m_Index) - { - const CTile ResultTile = {(unsigned char)Result}; - pGLayer->SetTile(x + OffsetX, y + OffsetY, ResultTile); - Changes++; - } - } - } - - vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup)); - char aDisplay[256]; - str_format(aDisplay, sizeof(aDisplay), "Construct '%s' game tiles (x%d)", s_apGametileOpNames[Selected], Changes); - m_pEditor->m_EditorHistory.RecordAction(std::make_shared(m_pEditor, vpActions, aDisplay, true)); } - else + + std::shared_ptr pTLayer = m_pEditor->m_Map.m_pTeleLayer; + int TeleLayerIndex = std::find(m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(), m_pEditor->m_Map.m_pGameGroup->m_vpLayers.end(), pTLayer) - m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(); + + if(pTLayer->m_Width < m_Width + OffsetX || pTLayer->m_Height < m_Height + OffsetY) { - if(!m_pEditor->m_Map.m_pTeleLayer) - { - std::shared_ptr pLayer = std::make_shared(m_pEditor, m_Width, m_Height); - m_pEditor->m_Map.MakeTeleLayer(pLayer); - m_pEditor->m_Map.m_pGameGroup->AddLayer(pLayer); + std::map> savedLayers; + savedLayers[LAYERTYPE_TILES] = pTLayer->Duplicate(); + savedLayers[LAYERTYPE_TELE] = savedLayers[LAYERTYPE_TILES]; - vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, m_pEditor->m_Map.m_pGameGroup->m_vpLayers.size() - 1)); + int PrevW = pTLayer->m_Width; + int PrevH = pTLayer->m_Height; + int NewW = pTLayer->m_Width < m_Width + OffsetX ? m_Width + OffsetX : pTLayer->m_Width; + int NewH = pTLayer->m_Height < m_Height + OffsetY ? m_Height + OffsetY : pTLayer->m_Height; + pTLayer->Resize(NewW, NewH); + std::shared_ptr Action1, Action2; + vpActions.push_back(Action1 = std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, TeleLayerIndex, ETilesProp::PROP_WIDTH, PrevW, NewW)); + vpActions.push_back(Action2 = std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, TeleLayerIndex, ETilesProp::PROP_HEIGHT, PrevH, NewH)); - if(m_Width != pGLayer->m_Width || m_Height > pGLayer->m_Height) - { - std::map> savedLayers; - savedLayers[LAYERTYPE_TILES] = pGLayer->Duplicate(); - savedLayers[LAYERTYPE_GAME] = savedLayers[LAYERTYPE_TILES]; - - int NewW = pGLayer->m_Width; - int NewH = pGLayer->m_Height; - if(m_Width > pGLayer->m_Width) - { - NewW = m_Width; - } - if(m_Height > pGLayer->m_Height) - { - NewH = m_Height; - } - - int PrevW = pGLayer->m_Width; - int PrevH = pGLayer->m_Height; - pLayer->Resize(NewW, NewH); - vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_WIDTH, PrevW, NewW)); - const std::shared_ptr &Action1 = std::static_pointer_cast(vpActions[vpActions.size() - 1]); - vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, GameLayerIndex, ETilesProp::PROP_HEIGHT, PrevH, NewH)); - const std::shared_ptr &Action2 = std::static_pointer_cast(vpActions[vpActions.size() - 1]); - - Action1->SetSavedLayers(savedLayers); - Action2->SetSavedLayers(savedLayers); - } - } - - std::shared_ptr pTLayer = m_pEditor->m_Map.m_pTeleLayer; - int TeleLayerIndex = std::find(m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(), m_pEditor->m_Map.m_pGameGroup->m_vpLayers.end(), pTLayer) - m_pEditor->m_Map.m_pGameGroup->m_vpLayers.begin(); - - if(pTLayer->m_Width < m_Width + OffsetX || pTLayer->m_Height < m_Height + OffsetY) - { - std::map> savedLayers; - savedLayers[LAYERTYPE_TILES] = pTLayer->Duplicate(); - savedLayers[LAYERTYPE_TELE] = savedLayers[LAYERTYPE_TILES]; - - int PrevW = pTLayer->m_Width; - int PrevH = pTLayer->m_Height; - int NewW = pTLayer->m_Width < m_Width + OffsetX ? m_Width + OffsetX : pTLayer->m_Width; - int NewH = pTLayer->m_Height < m_Height + OffsetY ? m_Height + OffsetY : pTLayer->m_Height; - pTLayer->Resize(NewW, NewH); - std::shared_ptr Action1, Action2; - vpActions.push_back(Action1 = std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, TeleLayerIndex, ETilesProp::PROP_WIDTH, PrevW, NewW)); - vpActions.push_back(Action2 = std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup, TeleLayerIndex, ETilesProp::PROP_HEIGHT, PrevH, NewH)); - - Action1->SetSavedLayers(savedLayers); - Action2->SetSavedLayers(savedLayers); - } - - int Changes = 0; - for(int y = OffsetY < 0 ? -OffsetY : 0; y < m_Height; y++) - { - for(int x = OffsetX < 0 ? -OffsetX : 0; x < m_Width; x++) - { - if(GetTile(x, y).m_Index) - { - auto TileIndex = (y + OffsetY) * pTLayer->m_Width + x + OffsetX; - Changes++; - - STeleTileStateChange::SData Previous{ - pTLayer->m_pTeleTile[TileIndex].m_Number, - pTLayer->m_pTeleTile[TileIndex].m_Type, - pTLayer->m_pTiles[TileIndex].m_Index}; - - pTLayer->m_pTiles[TileIndex].m_Index = TILE_AIR + Result; - pTLayer->m_pTeleTile[TileIndex].m_Number = 1; - pTLayer->m_pTeleTile[TileIndex].m_Type = TILE_AIR + Result; - - STeleTileStateChange::SData Current{ - pTLayer->m_pTeleTile[TileIndex].m_Number, - pTLayer->m_pTeleTile[TileIndex].m_Type, - pTLayer->m_pTiles[TileIndex].m_Index}; - - pTLayer->RecordStateChange(x, y, Previous, Current); - } - } - } - - vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup)); - char aDisplay[256]; - str_format(aDisplay, sizeof(aDisplay), "Construct 'tele' game tiles (x%d)", Changes); - m_pEditor->m_EditorHistory.RecordAction(std::make_shared(m_pEditor, vpActions, aDisplay, true)); + Action1->SetSavedLayers(savedLayers); + Action2->SetSavedLayers(savedLayers); } + + int Changes = 0; + for(int y = OffsetY < 0 ? -OffsetY : 0; y < m_Height; y++) + { + for(int x = OffsetX < 0 ? -OffsetX : 0; x < m_Width; x++) + { + if(GetTile(x, y).m_Index) + { + auto TileIndex = (y + OffsetY) * pTLayer->m_Width + x + OffsetX; + Changes++; + + STeleTileStateChange::SData Previous{ + pTLayer->m_pTeleTile[TileIndex].m_Number, + pTLayer->m_pTeleTile[TileIndex].m_Type, + pTLayer->m_pTiles[TileIndex].m_Index}; + + pTLayer->m_pTiles[TileIndex].m_Index = TILE_AIR + Result; + pTLayer->m_pTeleTile[TileIndex].m_Number = 1; + pTLayer->m_pTeleTile[TileIndex].m_Type = TILE_AIR + Result; + + STeleTileStateChange::SData Current{ + pTLayer->m_pTeleTile[TileIndex].m_Number, + pTLayer->m_pTeleTile[TileIndex].m_Type, + pTLayer->m_pTiles[TileIndex].m_Index}; + + pTLayer->RecordStateChange(x, y, Previous, Current); + } + } + } + + vpActions.push_back(std::make_shared(m_pEditor, m_pEditor->m_SelectedGroup)); + char aDisplay[256]; + str_format(aDisplay, sizeof(aDisplay), "Construct 'tele' game tiles (x%d)", Changes); + m_pEditor->m_EditorHistory.RecordAction(std::make_shared(m_pEditor, vpActions, aDisplay, true)); } } +} + +bool CLayerTiles::CanFillGameTiles() const +{ + const bool EntitiesLayer = IsEntitiesLayer(); + if(EntitiesLayer) + return false; + + std::shared_ptr pGroup = m_pEditor->m_Map.m_vpGroups[m_pEditor->m_SelectedGroup]; + + // Game tiles can only be constructed if the layer is relative to the game layer + return !(pGroup->m_OffsetX % 32) && !(pGroup->m_OffsetY % 32) && pGroup->m_ParallaxX == 100 && pGroup->m_ParallaxY == 100; +} + +CUi::EPopupMenuFunctionResult CLayerTiles::RenderProperties(CUIRect *pToolBox) +{ + CUIRect Button; + + const bool EntitiesLayer = IsEntitiesLayer(); + + if(CanFillGameTiles()) + { + pToolBox->HSplitBottom(12.0f, pToolBox, &Button); + static int s_GameTilesButton = 0; + if(m_pEditor->DoButton_Editor(&s_GameTilesButton, "Game tiles", 0, &Button, 0, "Constructs game tiles from this layer")) + m_pEditor->PopupSelectGametileOpInvoke(m_pEditor->Ui()->MouseX(), m_pEditor->Ui()->MouseY()); + const int Selected = m_pEditor->PopupSelectGameTileOpResult(); + FillGameTiles((EGameTileOp)Selected); + } if(m_pEditor->m_Map.m_pGameLayer.get() != this) { diff --git a/src/game/editor/mapitems/layer_tiles.h b/src/game/editor/mapitems/layer_tiles.h index f5789a898..9af936281 100644 --- a/src/game/editor/mapitems/layer_tiles.h +++ b/src/game/editor/mapitems/layer_tiles.h @@ -2,6 +2,7 @@ #define GAME_EDITOR_MAPITEMS_LAYER_TILES_H #include +#include #include #include "layer.h" @@ -122,6 +123,8 @@ public: void BrushSelecting(CUIRect Rect) override; int BrushGrab(std::shared_ptr pBrush, CUIRect Rect) override; void FillSelection(bool Empty, std::shared_ptr pBrush, CUIRect Rect) override; + void FillGameTiles(EGameTileOp Fill); + bool CanFillGameTiles() const; void BrushDraw(std::shared_ptr pBrush, float wx, float wy) override; void BrushFlipX() override; void BrushFlipY() override; diff --git a/src/game/editor/quick_actions.cpp b/src/game/editor/quick_actions.cpp index 80b07c787..d1a063949 100644 --- a/src/game/editor/quick_actions.cpp +++ b/src/game/editor/quick_actions.cpp @@ -4,12 +4,28 @@ #include "editor_actions.h" +void CEditor::FillGameTiles(EGameTileOp FillTile) const +{ + std::shared_ptr pTileLayer = std::static_pointer_cast(GetSelectedLayerType(0, LAYERTYPE_TILES)); + if(pTileLayer) + pTileLayer->FillGameTiles(FillTile); +} + +bool CEditor::CanFillGameTiles() const +{ + std::shared_ptr pTileLayer = std::static_pointer_cast(GetSelectedLayerType(0, LAYERTYPE_TILES)); + if(pTileLayer) + return pTileLayer->CanFillGameTiles(); + return false; +} + void CEditor::AddGroup() { m_Map.NewGroup(); m_SelectedGroup = m_Map.m_vpGroups.size() - 1; m_EditorHistory.RecordAction(std::make_shared(this, m_SelectedGroup, false)); } + void CEditor::AddTileLayer() { std::shared_ptr pTileLayer = std::make_shared(this, m_Map.m_pGameLayer->m_Width, m_Map.m_pGameLayer->m_Height); diff --git a/src/game/editor/quick_actions.h b/src/game/editor/quick_actions.h index 2e4f7b8dd..d8012117e 100644 --- a/src/game/editor/quick_actions.h +++ b/src/game/editor/quick_actions.h @@ -7,6 +7,110 @@ #define ALWAYS_FALSE []() -> bool { return false; } #define DEFAULT_BTN []() -> int { return -1; } +REGISTER_QUICK_ACTION( + GameTilesAir, + "Game tiles: Air", + [&]() { FillGameTiles(EGameTileOp::AIR); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesHookable, + "Game tiles: Hookable", + [&]() { FillGameTiles(EGameTileOp::HOOKABLE); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesDeath, + "Game tiles: Death", + [&]() { FillGameTiles(EGameTileOp::DEATH); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesUnhookable, + "Game tiles: Unhookable", + [&]() { FillGameTiles(EGameTileOp::UNHOOKABLE); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesHookthrough, + "Game tiles: Hookthrough", + [&]() { FillGameTiles(EGameTileOp::HOOKTHROUGH); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesFreeze, + "Game tiles: Freeze", + [&]() { FillGameTiles(EGameTileOp::FREEZE); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesUnfreeze, + "Game tiles: Unfreeze", + [&]() { FillGameTiles(EGameTileOp::UNFREEZE); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesDeepFreeze, + "Game tiles: Deep Freeze", + [&]() { FillGameTiles(EGameTileOp::DEEP_FREEZE); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesDeepUnfreeze, + "Game tiles: Deep Unfreeze", + [&]() { FillGameTiles(EGameTileOp::DEEP_UNFREEZE); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesBlueCheckTele, + "Game tiles: Blue Check Tele", + [&]() { FillGameTiles(EGameTileOp::BLUE_CHECK_TELE); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesRedCheckTele, + "Game tiles: Red Check Tele", + [&]() { FillGameTiles(EGameTileOp::RED_CHECK_TELE); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesLiveFreeze, + "Game tiles: Live Freeze", + [&]() { FillGameTiles(EGameTileOp::LIVE_FREEZE); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") +REGISTER_QUICK_ACTION( + GameTilesLiveUnfreeze, + "Game tiles: Live Unfreeze", + [&]() { FillGameTiles(EGameTileOp::LIVE_UNFREEZE); }, + [&]() -> bool { return !CanFillGameTiles(); }, + ALWAYS_FALSE, + DEFAULT_BTN, + "") REGISTER_QUICK_ACTION( AddGroup, "Add group", [&]() { AddGroup(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "Adds a new group") REGISTER_QUICK_ACTION(