From 3914106f350bdf6aa8613d5dfa2b68f240fbac28 Mon Sep 17 00:00:00 2001 From: Jonathan Wilson Date: Tue, 17 Oct 2023 08:36:05 +1000 Subject: [PATCH] Implement more of ControlBar --- src/CMakeLists.txt | 1 + src/game/client/gui/controlbar/controlbar.cpp | 290 +++++- src/game/client/gui/controlbar/controlbar.h | 40 +- .../gui/controlbar/controlbarbeacon.cpp | 53 + .../gui/controlbar/controlbarcommand.cpp | 886 ++++++++++++++++- .../controlbarcommandprocessing.cpp | 16 +- .../gui/controlbar/controlbarmultiselect.cpp | 190 +++- .../gui/controlbar/controlbarresizer.cpp | 3 + .../gui/controlbar/controlbarscheme.cpp | 936 +++++++++++++++++- .../client/gui/controlbar/controlbarscheme.h | 3 +- .../controlbarunderconstruction.cpp | 17 + .../client/gui/gadget/gadgetpushbutton.cpp | 14 + src/game/common/ini/ini.cpp | 2 +- .../logic/object/behavior/behaviormodule.h | 38 +- src/game/logic/object/update/aiupdate.h | 8 +- .../logic/object/update/battleplanupdate.cpp | 24 + .../logic/object/update/battleplanupdate.h | 82 ++ src/hooker/setuphooks_zh.cpp | 35 + 18 files changed, 2594 insertions(+), 44 deletions(-) create mode 100644 src/game/logic/object/update/battleplanupdate.cpp create mode 100644 src/game/logic/object/update/battleplanupdate.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c1c6dccfa..8b24e53d6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -330,6 +330,7 @@ set(GAMEENGINE_SRC game/logic/object/update/aiupdate/dozeraiupdate.cpp game/logic/object/update/assistedtargetingupdate.cpp game/logic/object/update/autodepositupdate.cpp + game/logic/object/update/battleplanupdate.cpp game/logic/object/update/laserupdate.cpp game/logic/object/update/physicsupdate.cpp game/logic/object/update/projectilestreamupdate.cpp diff --git a/src/game/client/gui/controlbar/controlbar.cpp b/src/game/client/gui/controlbar/controlbar.cpp index b98d118c7..2fb10be77 100644 --- a/src/game/client/gui/controlbar/controlbar.cpp +++ b/src/game/client/gui/controlbar/controlbar.cpp @@ -19,6 +19,7 @@ #include "captainslog.h" #include "colorspace.h" #include "controlbarscheme.h" +#include "display.h" #include "drawable.h" #include "gadgetprogressbar.h" #include "gadgetpushbutton.h" @@ -33,10 +34,12 @@ #include "player.h" #include "playerlist.h" #include "playertemplate.h" +#include "recorder.h" #include "scriptengine.h" #include "specialpower.h" #include "stealthupdate.h" #include "thingfactory.h" +#include "view.h" #include "windowlayout.h" #include "windowvideomanager.h" #ifdef GAME_DLL @@ -322,7 +325,7 @@ bool CommandButton::Is_Valid_To_Use_On(Object *obj, const Object *obj2, const Co if (interface != nullptr) { for (const ProductionEntry *entry = interface->First_Production(); entry; entry = interface->Next_Production(entry)) { - if (entry->Get_Production_Object() != nullptr) { + if (entry->Get_Production_Upgrade() != nullptr) { return false; } } @@ -399,7 +402,7 @@ bool CommandButton::Is_Context_Command() const return (m_options & COMMAND_OPTION_CONTEXTMODE_COMMAND) != 0; } -void CommandButton::Copy_Images_From(const CommandButton *button, bool set_dirty) +void CommandButton::Copy_Images_From(const CommandButton *button, bool set_dirty) const { if (m_buttonImage != button->Get_Button_Image()) { m_buttonImage = button->Get_Button_Image(); @@ -410,7 +413,7 @@ void CommandButton::Copy_Images_From(const CommandButton *button, bool set_dirty } } -void CommandButton::Copy_Button_Text_From(const CommandButton *button, bool conflicting_label, bool set_dirty) +void CommandButton::Copy_Button_Text_From(const CommandButton *button, bool conflicting_label, bool set_dirty) const { bool is_dirty = false; @@ -474,7 +477,7 @@ ControlBar::ControlBar() : m_controlBarSchemeManager(nullptr), m_currentSelectedDrawable(nullptr), m_currContext(CB_CONTEXT_NONE), - m_rallyPointDrawable(nullptr), + m_rallyPointDrawableID(INVALID_DRAWABLE_ID), m_displayedConstructPercent(-1.0f), m_oclTimerFrame(0), m_displayedQueueCount(0), @@ -504,7 +507,7 @@ ControlBar::ControlBar() : m_observerPlayer(nullptr), m_controlBarPopupDescriptionLayout(nullptr), m_buildTooltipLayoutVisible(false), - m_unkColor(Make_Color(0, 0, 0, 100)), + m_CommandBarBorderColor(Make_Color(0, 0, 0, 100)), m_barButtonGenStarOnIcon(nullptr), m_barButtonGenStarOffIcon(nullptr), m_toggleButtonUpInImage(nullptr), @@ -965,7 +968,7 @@ void ControlBar::Set_Command_Bar_Border(GameWindow *button, CommandButtonMappedB void ControlBar::Reset() { Hide_Special_Power_Shortcut(); - m_rallyPointDrawable = nullptr; + m_rallyPointDrawableID = INVALID_DRAWABLE_ID; if (m_radarAttackGlowWindow != nullptr) { m_radarAttackGlowWindow->Win_Enable(true); @@ -1474,6 +1477,21 @@ void ControlBar::Parse_Command_Set_Definition(INI *ini) ini->Init_From_INI(commandset, CommandSet::Get_Field_Parse()); } +void ControlBar::Parse_Control_Bar_Scheme_Definition(INI *ini) +{ + Utf8String name; + name.Set(ini->Get_Next_Token()); + ControlBarSchemeManager *manager = g_theControlBar->Get_Control_Bar_Scheme_Manager(); + captainslog_dbgassert(manager != nullptr, "Parse_Control_Bar_Scheme_Definition: Unable to Get ControlBarSchemeManager"); + + if (manager != nullptr) { + ControlBarScheme *scheme = manager->New_Control_Bar_Scheme(name); + captainslog_dbgassert( + scheme != nullptr, "Parse_Control_Bar_Scheme_Definition: Unable to allocate Scheme '%s'", name.Str()); + ini->Init_From_INI(scheme, ControlBarSchemeManager::Get_Field_Parse()); + } +} + CommandButton *ControlBar::Find_Non_Const_Command_Button(const Utf8String &name) { for (CommandButton *button = m_commandButtons; button != nullptr; button = button->Get_Next()) { @@ -1559,6 +1577,266 @@ CommandSet *ControlBar::New_Command_Set_Override(CommandSet *set) return new_set; } +void ControlBar::Show_Rally_Point(const Coord3D *loc) +{ + if (loc != nullptr) { + Drawable *drawable = nullptr; + + if (m_rallyPointDrawableID != INVALID_DRAWABLE_ID) { + drawable = g_theGameClient->Find_Drawable_By_ID(m_rallyPointDrawableID); + } else { + drawable = g_theThingFactory->New_Drawable( + g_theThingFactory->Find_Template("RallyPointMarker", true), DRAWABLE_STATUS_UNK); + captainslog_dbgassert(drawable != nullptr, "Show_Rally_Point: Unable to create rally point drawable"); + + if (drawable != nullptr) { + drawable->Set_Status_Bit(DRAWABLE_STATUS_16); + m_rallyPointDrawableID = drawable->Get_ID(); + } + } + + captainslog_dbgassert(drawable != nullptr, "Show_Rally_Point: No rally point marker found"); + drawable->Set_Position(loc); + drawable->Set_Orientation(g_theWriteableGlobalData->m_downWindAngle); + + if (g_theWriteableGlobalData->m_timeOfDay == TIME_OF_DAY_NIGHT) { + drawable->Set_Indicator_Color(g_thePlayerList->Get_Local_Player()->Get_Night_Color()); + } else { + drawable->Set_Indicator_Color(g_thePlayerList->Get_Local_Player()->Get_Color()); + } + } else { + if (m_rallyPointDrawableID != INVALID_DRAWABLE_ID) { + g_theGameClient->Destroy_Drawable(g_theGameClient->Find_Drawable_By_ID(m_rallyPointDrawableID)); + } + + m_rallyPointDrawableID = INVALID_DRAWABLE_ID; + } +} + +void ControlBar::Switch_Control_Bar_Stage(ControlBarStages stage) +{ + if (stage < CONTROL_BAR_STAGE_MAX + && (g_theRecorder == nullptr || g_theRecorder->Get_Mode() != RECORDERMODETYPE_PLAYBACK)) { + switch (stage) { + case CONTROL_BAR_STAGE_DEFAULT: + Set_Default_Control_Bar_Config(); + break; + case CONTROL_BAR_STAGE_LOW: + Set_Low_Control_Bar_Config(); + break; + case CONTROL_BAR_STAGE_HIDDEN: + Set_Hidden_Control_Bar(); + break; + default: + captainslog_dbgassert( + false, "ControlBar::Switch_Control_Bar_Stage we were passed in a stage that's not supported %d", stage); + break; + } + } +} + +void ControlBar::Set_Default_Control_Bar_Config() +{ + m_controlBarConfig = CONTROL_BAR_STAGE_DEFAULT; + g_theTacticalView->Set_Height(g_theDisplay->Get_Height() * 0.8f); + m_contextParent[0]->Win_Set_Position(m_parentXPosition, m_parentYPosition); + m_contextParent[0]->Win_Hide(false); + Repopulate_Build_Tooltip_Layout(); + Set_Up_Down_Images(); +} + +void ControlBar::Set_Hidden_Control_Bar() +{ + m_controlBarConfig = CONTROL_BAR_STAGE_HIDDEN; + m_contextParent[0]->Win_Hide(true); +} + +void ControlBar::Set_Low_Control_Bar_Config() +{ + m_controlBarConfig = CONTROL_BAR_STAGE_LOW; + int x_pos = m_parentXPosition; + int y_pos = (float)g_theDisplay->Get_Height() - (float)g_theDisplay->Get_Height() * 0.1f; + g_theTacticalView->Set_Height(g_theDisplay->Get_Height()); + m_contextParent[0]->Win_Set_Position(x_pos, y_pos); + m_contextParent[0]->Win_Hide(false); +} + +void ControlBar::Set_Up_Down_Images() +{ + GameWindow *window = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:ButtonLarge")); + + if (window != nullptr) { + if (m_controlBarConfig == CONTROL_BAR_STAGE_LOW) { + Gadget_Button_Set_Enabled_Image(window, m_toggleButtonUpOnImage); + Gadget_Button_Set_Hilite_Image(window, m_toggleButtonUpInImage); + Gadget_Button_Set_Hilite_Selected_Image(window, m_toggleButtonUpPushedImage); + } else { + Gadget_Button_Set_Enabled_Image(window, m_toggleButtonDownOnImage); + Gadget_Button_Set_Hilite_Image(window, m_toggleButtonDownInImage); + Gadget_Button_Set_Hilite_Selected_Image(window, m_toggleButtonDownPushedImage); + } + } +} + +void ControlBar::Update_Build_Queue_Disabled_Images(const Image *image) +{ + if (image != nullptr) { + static bool ids_initialized = false; + static NameKeyType build_queue_ids[QUEUE_ENTRY_COUNT]; + + if (!ids_initialized) { + Utf8String name; + + for (int i = 0; i < QUEUE_ENTRY_COUNT; i++) { + name.Format("ControlBar.wnd:ButtonQueue%02d", i + 1); + build_queue_ids[i] = g_theNameKeyGenerator->Name_To_Key(name.Str()); + } + + ids_initialized = true; + } + + for (int i = 0; i < QUEUE_ENTRY_COUNT; i++) { + m_queueData[i].control = g_theWindowManager->Win_Get_Window_From_Id(m_contextParent[3], build_queue_ids[i]); + Gadget_Button_Set_Disabled_Image(m_queueData[i].control, image); + } + } +} + +void ControlBar::Update_Build_Up_Clock_Color(int color) +{ + m_buildUpClockColor = color; +} + +void ControlBar::Update_Right_HUD_Image(const Image *image) +{ + if (m_rightHUDWindow != nullptr) { + if (image != nullptr) { + m_rightHUDWindow->Win_Set_Enabled_Image(0, image); + } + } +} + +void ControlBar::Update_Slot_Exit_Image(const Image *image) +{ + if (image != nullptr) { + CommandButton *button = Find_Non_Const_Command_Button("Command_StructureExit"); + + if (button != nullptr) { + button->Set_Button_Image(image); + } + + button = Find_Non_Const_Command_Button("Command_TransportExit"); + + if (button != nullptr) { + button->Set_Button_Image(image); + } + + button = Find_Non_Const_Command_Button("Command_BunkerExit"); + + if (button != nullptr) { + button->Set_Button_Image(image); + } + + button = Find_Non_Const_Command_Button("Command_FireBaseExit"); + + if (button != nullptr) { + button->Set_Button_Image(image); + } + } +} + +void ControlBar::Update_Up_Down_Images(const Image *toggle_button_up_in_image, + const Image *toggle_button_up_on_image, + const Image *toggle_button_up_pushed_image, + const Image *toggle_button_down_in_image, + const Image *toggle_button_down_on_image, + const Image *toggle_button_down_pushed_image, + const Image *general_button_enable_image, + const Image *general_button_hilited_image) +{ + m_toggleButtonUpInImage = toggle_button_up_in_image; + m_toggleButtonUpOnImage = toggle_button_up_on_image; + m_toggleButtonUpPushedImage = toggle_button_up_pushed_image; + m_toggleButtonDownInImage = toggle_button_down_in_image; + m_toggleButtonDownOnImage = toggle_button_down_on_image; + m_toggleButtonDownPushedImage = toggle_button_down_pushed_image; + m_generalButtonEnableImage = general_button_enable_image; + m_generalButtonHilitedImage = general_button_hilited_image; + Set_Up_Down_Images(); +} + +void ControlBar::On_Drawable_Selected(Drawable *draw) +{ + Mark_UI_Dirty(); + g_theInGameUI->Set_GUI_Command(nullptr); +} + +void ControlBar::On_Drawable_Deselected(Drawable *draw) +{ + Mark_UI_Dirty(); + + if (g_theInGameUI->Get_Select_Count() == 0) { + g_theInGameUI->Set_GUI_Command(nullptr); + } + + g_theInGameUI->Place_Build_Available(nullptr, nullptr); +} + +CBCommandStatus ControlBar::Process_Context_Sensitive_Button_Transition(GameWindow *button, GadgetGameMessage gadget_message) +{ + return Process_Command_Transition_UI(button, gadget_message); +} + +void ControlBar::Set_Control_Bar_Scheme_By_Name(const Utf8String &name) +{ + if (m_controlBarSchemeManager != nullptr) { + m_controlBarSchemeManager->Set_Control_Bar_Scheme(name); + } + + Switch_Control_Bar_Stage(CONTROL_BAR_STAGE_DEFAULT); +} + +void ControlBar::Preload_Assets(TimeOfDayType time_of_day) +{ + if (m_controlBarSchemeManager != nullptr) { + m_controlBarSchemeManager->Preload_Assets(time_of_day); + } +} + +void ControlBar::Update_Purchase_Science() {} + +void ControlBar::Toggle_Control_Bar_Stage() +{ + if (m_controlBarConfig != CONTROL_BAR_STAGE_DEFAULT) { + Switch_Control_Bar_Stage(CONTROL_BAR_STAGE_DEFAULT); + } else { + Switch_Control_Bar_Stage(CONTROL_BAR_STAGE_LOW); + } +} + +void ControlBar::Update_Command_Marker_Image(const Image *image) {} + +void ControlBar::Get_Foreground_Marker_Pos(int *x, int *y) +{ + *x = m_foregroundMarkerPosX; + *y = m_foregroundMarkerPosY; +} + +void ControlBar::Draw_Transition_Handler() {} + +void ControlBar::Trigger_Radar_Attack_Glow() +{ + if (m_radarAttackGlowWindow != nullptr) { + m_triggerRadarAttackGlow = true; + m_radarAttackGlowCounter = 150; + + if ((m_radarAttackGlowWindow->Win_Get_Status() & WIN_STATUS_ENABLED) != 0) { + m_radarAttackGlowWindow->Win_Enable(false); + } + } +} + void ControlBar::Set_Control_Bar_Scheme_By_Player(Player *p) { #ifdef GAME_DLL diff --git a/src/game/client/gui/controlbar/controlbar.h b/src/game/client/gui/controlbar/controlbar.h index 2e03d51ce..783d65d54 100644 --- a/src/game/client/gui/controlbar/controlbar.h +++ b/src/game/client/gui/controlbar/controlbar.h @@ -42,7 +42,11 @@ enum ControlBarContext enum ControlBarStages { + CONTROL_BAR_STAGE_DEFAULT, CONTROL_BAR_STAGE_UNK, + CONTROL_BAR_STAGE_LOW, + CONTROL_BAR_STAGE_HIDDEN, + CONTROL_BAR_STAGE_MAX, }; enum CBCommandStatus @@ -53,7 +57,12 @@ enum CBCommandStatus enum CommandAvailability { - COMMAND_AVAILIBLITY_UNK, + COMMAND_AVAILABLITY_UNK0, + COMMAND_AVAILABLITY_UNK1, + COMMAND_AVAILABLITY_UNK2, + COMMAND_AVAILABLITY_UNK3, + COMMAND_AVAILABLITY_UNK4, + COMMAND_AVAILABLITY_UNK5, }; class CommandSet : public Overridable @@ -196,7 +205,7 @@ class CommandButton : public Overridable void Set_Cameo_Flash_Time(int time) { m_cameoFlashTime = time; } void Set_Name(const Utf8String &name) { m_name = name; } - void Set_Button_Image(Image *image) { m_buttonImage = image; } + void Set_Button_Image(const Image *image) { m_buttonImage = image; } bool Is_Valid_Object_Target(const Player *player, const Object *obj) const; bool Is_Valid_Object_Target(const Object *obj1, const Object *obj2) const; @@ -205,8 +214,8 @@ class CommandButton : public Overridable bool Is_Ready(const Object *obj) const; bool Is_Valid_Object_Target(const Drawable *drawable, const Drawable *drawable2) const; bool Is_Context_Command() const; - void Copy_Images_From(const CommandButton *button, bool set_dirty); - void Copy_Button_Text_From(const CommandButton *button, bool conflicting_label, bool set_dirty); + void Copy_Images_From(const CommandButton *button, bool set_dirty) const; + void Copy_Button_Text_From(const CommandButton *button, bool conflicting_label, bool set_dirty) const; void Cache_Button_Image(); void Friend_Add_To_List(CommandButton **next); @@ -224,8 +233,8 @@ class CommandButton : public Overridable RadiusCursorType m_radiusCursorType; Utf8String m_cursorName; Utf8String m_invalidCursorName; - Utf8String m_textLabel; - Utf8String m_descriptLabel; + mutable Utf8String m_textLabel; + mutable Utf8String m_descriptLabel; Utf8String m_purchasedLabel; Utf8String m_conflictingLabel; WeaponSlotType m_weaponSlot; @@ -235,7 +244,7 @@ class CommandButton : public Overridable Utf8String m_buttonImageString; int m_unk; AudioEventRTS m_unitSpecificSound; - const Image *m_buttonImage; + mutable const Image *m_buttonImage; int m_cameoFlashTime; static FieldParse s_commandButtonFieldParseTable[]; }; @@ -250,7 +259,7 @@ class ControlBar : public SubsystemInterface union { ProductionID production_id; - UpgradeTemplate *upgrade_template; + const UpgradeTemplate *upgrade_template; }; }; @@ -279,14 +288,14 @@ class ControlBar : public SubsystemInterface bool Get_Build_Tooltip_Layout_Visible() const { return m_buildTooltipLayoutVisible; } const CommandButton *Get_Command_Buttons() const { return m_commandButtons; } - const ControlBarSchemeManager *Get_Control_Bar_Scheme_Manager() const { return m_controlBarSchemeManager; } + ControlBarSchemeManager *Get_Control_Bar_Scheme_Manager() const { return m_controlBarSchemeManager; } const Image *Get_Gen_Arrow_Image() const { return m_genArrowImage; } Player *Get_Observer_Player() const { return m_observerPlayer; } bool Is_Observer() const { return m_isObserver; } void Set_Cameo_Flash(bool flash) { m_cameoFlash = flash; } void Set_Gen_Arrow_Image(const Image *image) { m_genArrowImage = image; } void Set_Observer_Player(Player *player) { m_observerPlayer = player; } - void Set_Unk_Color(int color) { m_unkColor = color; } + void Set_Command_Bar_Border_Color(int color) { m_CommandBarBorderColor = color; } const CommandSet *Find_Command_Set(const Utf8String &name); const CommandButton *Find_Command_Button(const Utf8String &name); @@ -296,7 +305,7 @@ class ControlBar : public SubsystemInterface void Get_Background_Marker_Pos(int *x, int *y); CommandAvailability Get_Command_Availability( const CommandButton *button, Object *obj, GameWindow *window, GameWindow *window2, bool b); - const void Get_Foreground_Marker_Pos(int *x, int *y); + void Get_Foreground_Marker_Pos(int *x, int *y); const Image *Get_Star_Image(); void Hide_Build_Tooltip_Layout(); @@ -405,6 +414,7 @@ class ControlBar : public SubsystemInterface static void Parse_Command_Button_Definition(INI *ini); static void Parse_Command_Set_Definition(INI *ini); + static void Parse_Control_Bar_Scheme_Definition(INI *ini); static void Populate_Inv_Data_Callback(Object *obj, void *user_data); static const Image *Calculate_Veterancy_Overlay_For_Object(const Object *object); static const Image *Calculate_Veterancy_Overlay_For_Thing(const ThingTemplate *thing); @@ -429,7 +439,7 @@ class ControlBar : public SubsystemInterface GameWindow *m_contextParent[CONTEXT_PARENT_COUNT]; Drawable *m_currentSelectedDrawable; ControlBarContext m_currContext; - Drawable *m_rallyPointDrawable; + DrawableID m_rallyPointDrawableID; float m_displayedConstructPercent; unsigned int m_oclTimerFrame; unsigned int m_displayedQueueCount; @@ -450,7 +460,7 @@ class ControlBar : public SubsystemInterface WindowLayout *m_specialPowerShortcutBarLayout; GameWindow *m_specialPowerShortcutBarParent; GameWindow *m_commandWindows[CommandSet::MAX_COMMAND_BUTTONS]; - CommandButton *m_commonCommands[CommandSet::MAX_COMMAND_BUTTONS]; + const CommandButton *m_commonCommands[CommandSet::MAX_COMMAND_BUTTONS]; QueueEntry m_queueData[QUEUE_ENTRY_COUNT]; bool m_cameoFlash; bool m_unk1; @@ -473,7 +483,7 @@ class ControlBar : public SubsystemInterface int m_commandButtonBorderActionColor; int m_commandButtonBorderUpgradeColor; int m_commandButtonBorderSystemColor; - int m_unkColor; + int m_CommandBarBorderColor; const Image *m_barButtonGenStarOnIcon; const Image *m_barButtonGenStarOffIcon; const Image *m_toggleButtonUpInImage; @@ -507,6 +517,8 @@ class ControlBar : public SubsystemInterface }; void Control_Bar_Popup_Description_Update_Func(WindowLayout *layout, void *user_data); +WindowMsgHandledType Beacon_Window_Input( + GameWindow *text_entry, unsigned int message, unsigned int data_1, unsigned int data_2); void Hide_Control_Bar(bool hide); void Show_Control_Bar(bool hide); diff --git a/src/game/client/gui/controlbar/controlbarbeacon.cpp b/src/game/client/gui/controlbar/controlbarbeacon.cpp index 454a0d260..03fe15128 100644 --- a/src/game/client/gui/controlbar/controlbarbeacon.cpp +++ b/src/game/client/gui/controlbar/controlbarbeacon.cpp @@ -13,5 +13,58 @@ * LICENSE */ #include "controlbar.h" +#include "gadgettextentry.h" +#include "gamewindowmanager.h" +#include "keyboard.h" void ControlBar::Update_Context_Beacon() {} + +void ControlBar::Populate_Beacon(Object *beacon) +{ + Set_Portrait_By_Object(beacon); + static const NameKeyType text_id = g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:EditBeaconText"); + static const NameKeyType static_text_id = g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:StaticTextBeaconLabel"); + static const NameKeyType clear_button_id = g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:ButtonClearBeaconText"); + GameWindow *text = g_theWindowManager->Win_Get_Window_From_Id(nullptr, text_id); + GameWindow *static_text = g_theWindowManager->Win_Get_Window_From_Id(nullptr, static_text_id); + GameWindow *clear_button = g_theWindowManager->Win_Get_Window_From_Id(nullptr, clear_button_id); + + if (beacon->Is_Locally_Controlled()) { + if (text != nullptr) { + text->Win_Hide(false); + Gadget_Text_Entry_Set_Text(text, beacon->Get_Drawable()->Get_Caption_Text()); + g_theWindowManager->Win_Set_Focus(text); + } + + if (static_text != nullptr) { + static_text->Win_Hide(false); + } + + if (clear_button != nullptr) { + clear_button->Win_Hide(false); + } + } else { + if (text != nullptr) { + text->Win_Hide(true); + } + + if (static_text != nullptr) { + static_text->Win_Hide(true); + } + + if (clear_button != nullptr) { + clear_button->Win_Hide(true); + } + } +} + +WindowMsgHandledType Beacon_Window_Input( + GameWindow *text_entry, unsigned int message, unsigned int data_1, unsigned int data_2) +{ + if (message != GWM_CHAR || data_1 != Keyboard::KEY_ESCAPE) { + return MSG_IGNORED; + } + + g_theInGameUI->Deselect_All_Drawables(true); + return MSG_HANDLED; +} diff --git a/src/game/client/gui/controlbar/controlbarcommand.cpp b/src/game/client/gui/controlbar/controlbarcommand.cpp index 3bc5c644b..6442b923e 100644 --- a/src/game/client/gui/controlbar/controlbarcommand.cpp +++ b/src/game/client/gui/controlbar/controlbarcommand.cpp @@ -12,9 +12,18 @@ * A full copy of the GNU General Public License can be found in * LICENSE */ +#include "aiupdate.h" +#include "battleplanupdate.h" +#include "buildassistant.h" #include "controlbar.h" +#include "dozeraiupdate.h" #include "gadgetpushbutton.h" +#include "gamewindowmanager.h" +#include "overchargebehavior.h" #include "playerlist.h" +#include "playertemplate.h" +#include "specialabilityupdate.h" +#include "specialpower.h" #include "veterancygaincreate.h" struct PopulateInvButtonData @@ -125,9 +134,880 @@ const Image *ControlBar::Calculate_Veterancy_Overlay_For_Thing(const ThingTempla } } +void ControlBar::Do_Transport_Inventory_UI(Object *transport, const CommandSet *command_set) +{ + if (transport != nullptr) { + if (command_set != nullptr) { + ContainModuleInterface *contain = transport->Get_Contain(); + + if (contain != nullptr) { + int slots = contain->Get_Contain_Max(); + slots -= contain->Get_Extra_Slots_In_Use(); + int first_exit_index = -1; + int last_exit_index = -1; + int slot_count = 0; + + for (int i = 0; i < CommandSet::MAX_COMMAND_BUTTONS; i++) { + if (m_commandWindows[i] != nullptr) { + const CommandButton *command_button = command_set->Get_Command_Button(i); + + if (command_button != nullptr) { + if (command_button->Get_Command() == GUI_COMMAND_EXIT_CONTAINER) { + if (first_exit_index == -1) { + first_exit_index = i; + } + + last_exit_index = i; + slot_count++; + m_commandWindows[i]->Win_Hide(false); + m_commandWindows[i]->Win_Enable(false); + Gadget_Button_Draw_Overlay_Image(m_commandWindows[i], nullptr); + + if (transport->Get_Disabled_State(DISABLED_TYPE_DISABLED_UNMANNED)) { + m_commandWindows[i]->Win_Hide(false); + } + + if (slot_count > slots) { + m_commandWindows[i]->Win_Hide(true); + } + + Set_Control_Command(m_commandWindows[i], command_button); + } + } + } + } + + if (last_exit_index >= 0) { + PopulateInvButtonData data; + data.controls = m_commandWindows; + data.curr_index = first_exit_index; + data.max_index = last_exit_index; + data.transport = transport; + contain->Iterate_Contained(Populate_Inv_Data_Callback, &data, false); + } + + m_lastRecordedInventoryCount = contain->Get_Contain_Count(); + } + } + } +} + +void ControlBar::Populate_Command(Object *obj) +{ + Player *player = obj->Get_Controlling_Player(); + Reset_Contain_Data(); + Reset_Build_Queue_Data(); + const CommandSet *command_set = g_theControlBar->Find_Command_Set(obj->Get_Command_Set_String()); + + if (command_set == nullptr) { + for (int i = 0; i < CommandSet::MAX_COMMAND_BUTTONS; i++) { + if (m_commandWindows[i] != nullptr) { + m_commandWindows[i]->Win_Hide(true); + } + } + + return; + } + + if (obj->Get_Contain() != nullptr) { + ContainModuleInterface *contain = obj->Get_Contain(); + + if (contain->Is_Displayed_On_Control_Bar()) { + Do_Transport_Inventory_UI(obj, command_set); + } + } + + for (int i = 0; i < CommandSet::MAX_COMMAND_BUTTONS; i++) { + if (m_commandWindows[i] == nullptr) { + continue; + } + + const CommandButton *command_button = command_set->Get_Command_Button(i); + + if (command_button == nullptr || (command_button->Get_Options() & COMMAND_OPTION_SCRIPT_ONLY) != 0) { + m_commandWindows[i]->Win_Hide(true); + continue; + } + + if (command_button->Get_Command() != GUI_COMMAND_EXIT_CONTAINER) { + m_commandWindows[i]->Win_Hide(false); + m_commandWindows[i]->Win_Enable(true); + Set_Control_Command(m_commandWindows[i], command_button); + + if ((command_button->Get_Options() & COMMAND_OPTION_NEED_SPECIAL_POWER_SCIENCE) != 0) { + const SpecialPowerTemplate *power = command_button->Get_Special_Power(); + + if (power != nullptr) { + if (power->Get_Required_Science() != SCIENCE_INVALID + && command_button->Get_Command() != GUI_COMMAND_PURCHASE_SCIENCE + && command_button->Get_Command() != GUI_COMMAND_PLAYER_UPGRADE + && command_button->Get_Command() != GUI_COMMAND_OBJECT_UPGRADE) { + + if (!player->Has_Science(power->Get_Required_Science())) { + m_commandWindows[i]->Win_Hide(true); + continue; + } + + int owned_science_index = -1; + ScienceType science; + + for (unsigned int j = 0; j < command_button->Get_Sciences()->size(); j++) { + science = (*command_button->Get_Sciences())[j]; + + if (!player->Has_Science(science)) { + break; + } + + owned_science_index = j; + } + + if (owned_science_index != -1) { + science = (*command_button->Get_Sciences())[owned_science_index]; + + if (player != nullptr) { + if (player->Get_Player_Template() != nullptr) { + if (!player->Get_Player_Template()->Get_Purchase_Command_Set_Rank_One().Is_Empty()) { + if (!player->Get_Player_Template() + ->Get_Purchase_Command_Set_Rank_Three() + .Is_Empty()) { + if (!player->Get_Player_Template() + ->Get_Purchase_Command_Set_Rank_Eight() + .Is_Empty()) { + const CommandSet *rank_one = g_theControlBar->Find_Command_Set( + player->Get_Player_Template()->Get_Purchase_Command_Set_Rank_One()); + const CommandSet *rank_three = g_theControlBar->Find_Command_Set( + player->Get_Player_Template()->Get_Purchase_Command_Set_Rank_Three()); + const CommandSet *rank_eight = g_theControlBar->Find_Command_Set( + player->Get_Player_Template()->Get_Purchase_Command_Set_Rank_Eight()); + + if (rank_one != nullptr) { + if (rank_three != nullptr && rank_eight != nullptr) { + bool found = false; + + for (int button_idx = 0; !found && button_idx < RANK_1_BUTTON_COUNT; + button_idx++) { + const CommandButton *button = + rank_one->Get_Command_Button(button_idx); + + if (button != nullptr + && button->Get_Command() == GUI_COMMAND_PURCHASE_SCIENCE) { + if (button->Get_Sciences()->empty()) { + captainslog_dbgassert(false, + "Commandbutton %s is a purchase science button " + "without any science! Please add it.", + button->Get_Name().Str()); + } else { + if ((*button->Get_Sciences())[0] == science) { + command_button->Copy_Images_From(button, true); + command_button->Copy_Button_Text_From( + button, false, true); + found = true; + break; + } + } + } + } + + for (int button_idx = 0; !found && button_idx < RANK_3_BUTTON_COUNT; + button_idx++) { + const CommandButton *button = + rank_three->Get_Command_Button(button_idx); + + if (button != nullptr + && button->Get_Command() == GUI_COMMAND_PURCHASE_SCIENCE) { + if (button->Get_Sciences()->empty()) { + captainslog_dbgassert(false, + "Commandbutton %s is a purchase science button " + "without any science! Please add it.", + button->Get_Name().Str()); + } else { + if ((*button->Get_Sciences())[0] == science) { + command_button->Copy_Images_From(button, true); + command_button->Copy_Button_Text_From( + button, false, true); + found = true; + break; + } + } + } + } + + for (int button_idx = 0; !found && button_idx < RANK_8_BUTTON_COUNT; + button_idx++) { + const CommandButton *button = + rank_eight->Get_Command_Button(button_idx); + + if (button != nullptr + && button->Get_Command() == GUI_COMMAND_PURCHASE_SCIENCE) { + if (button->Get_Sciences()->empty()) { + captainslog_dbgassert(false, + "Commandbutton %s is a purchase science button " + "without any science! Please add it.", + button->Get_Name().Str()); + } else { + if ((*button->Get_Sciences())[0] == science) { + command_button->Copy_Images_From(button, true); + command_button->Copy_Button_Text_From( + button, false, true); + found = true; + break; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + + ExitInterface *exit = obj->Get_Object_Exit_Interface(); + + if (exit != nullptr) { + Show_Rally_Point(exit->Get_Rally_Point()); + } + + Update_Context_Command(); +} + +void ControlBar::Populate_Build_Queue(Object *producer) +{ + static const CommandButton *cancel_unit_command = Find_Command_Button("Command_CancelUnitCreate"); + static const CommandButton *cancel_upgrade_command = Find_Command_Button("Command_CancelUpgradeCreate"); + Reset_Build_Queue_Data(); + static bool ids_initialized = false; + static NameKeyType build_queue_ids[QUEUE_ENTRY_COUNT]; + + if (!ids_initialized) { + Utf8String name; + + for (int i = 0; i < QUEUE_ENTRY_COUNT; i++) { + name.Format("ControlBar.wnd:ButtonQueue%02d", i + 1); + build_queue_ids[i] = g_theNameKeyGenerator->Name_To_Key(name.Str()); + } + + ids_initialized = true; + } + + for (int i = 0; i < QUEUE_ENTRY_COUNT; i++) { + m_queueData[i].control = g_theWindowManager->Win_Get_Window_From_Id(m_contextParent[3], build_queue_ids[i]); + m_queueData[i].control->Win_Enable(false); + m_queueData[i].control->Win_Clear_Status(WIN_STATUS_USE_OVERLAY_STATES); + Gadget_Button_Set_Text(m_queueData[i].control, U_CHAR("")); + Gadget_Button_Draw_Overlay_Image(m_queueData[i].control, nullptr); + } + + ProductionUpdateInterface *production = producer->Get_Production_Update_Interface(); + + if (production != nullptr) { + int count = 0; + + for (const ProductionEntry *entry = production->First_Production(); entry != nullptr && count < QUEUE_ENTRY_COUNT; + entry = production->Next_Production(entry)) { + if (entry->Get_Type() == ProductionEntry::PRODUCTION_UNIT) { + Set_Control_Command(m_queueData[count].control, cancel_unit_command); + m_queueData[count].type = ProductionEntry::PRODUCTION_UNIT; + m_queueData[count].production_id = entry->Get_Production_ID(); + m_queueData[count].control->Win_Enable(true); + m_queueData[count].control->Win_Set_Status(WIN_STATUS_USE_OVERLAY_STATES); + Gadget_Button_Set_Enabled_Image( + m_queueData[count].control, entry->Get_Production_Object()->Get_Button_Image()); + Gadget_Button_Draw_Overlay_Image( + m_queueData[count].control, Calculate_Veterancy_Overlay_For_Thing(entry->Get_Production_Object())); + } else { + Set_Control_Command(m_queueData[count].control, cancel_upgrade_command); + m_queueData[count].type = ProductionEntry::PRODUCTION_UPGRADE; + m_queueData[count].upgrade_template = entry->Get_Production_Upgrade(); + m_queueData[count].control->Win_Enable(true); + m_queueData[count].control->Win_Set_Status(WIN_STATUS_USE_OVERLAY_STATES); + Gadget_Button_Set_Enabled_Image( + m_queueData[count].control, entry->Get_Production_Upgrade()->Get_Button_Image()); + } + + count++; + } + } + + m_displayedQueueCount = production->Get_Production_Count(); +} + void ControlBar::Update_Context_Command() { -#ifdef GAME_DLL - Call_Method(PICK_ADDRESS(0x005A3B20, 0x008E3643), this); -#endif + Object *obj = nullptr; + + if (m_currentSelectedDrawable != nullptr) { + obj = m_currentSelectedDrawable->Get_Object(); + } + + ContainModuleInterface *contain; + + if (obj != nullptr) { + contain = obj->Get_Contain(); + } else { + contain = nullptr; + } + + if (contain != nullptr && contain->Get_Contain_Max() > 0 + && m_lastRecordedInventoryCount != contain->Get_Contain_Count()) { + m_lastRecordedInventoryCount = contain->Get_Contain_Count(); + Evaluate_Context_UI(); + } + + ProductionUpdateInterface *production; + + if (obj != nullptr) { + production = obj->Get_Production_Update_Interface(); + } else { + production = nullptr; + } + + if (m_contextParent[3]->Win_Is_Hidden()) { + if (production != nullptr && production->First_Production() != nullptr) { + Set_Portrait_By_Object(nullptr); + m_contextParent[3]->Win_Hide(false); + Populate_Build_Queue(obj); + } + } else if (production != nullptr && production->First_Production() == nullptr) { + m_contextParent[3]->Win_Hide(true); + Set_Portrait_By_Object(obj); + } + + if (!m_contextParent[3]->Win_Is_Hidden()) { + Set_Portrait_By_Object(nullptr); + + if (production != nullptr) { + if (production->Get_Production_Count() != m_displayedQueueCount) { + Populate_Build_Queue(obj); + } + + const ProductionEntry *entry = production->First_Production(); + + if (entry != nullptr) { + static const NameKeyType win_id = g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:ButtonQueue01"); + GameWindow *window = g_theWindowManager->Win_Get_Window_From_Id(m_contextParent[3], win_id); + captainslog_dbgassert(window != nullptr, "Update_Context_Command: Unable to find first build queue button"); + Gadget_Button_Draw_Inverse_Clock(window, entry->Get_Percent_Complete(), m_buildUpClockColor); + } + } + } + + for (int i = 0; i < CommandSet::MAX_COMMAND_BUTTONS; i++) { + if (m_commandWindows[i] != nullptr) { + GameWindow *window = m_commandWindows[i]; + + if (!window->Win_Is_Hidden()) { + CommandButton *button = static_cast(Gadget_Button_Get_Data(window)); + + if (button != nullptr) { + window->Win_Clear_Status(WIN_STATUS_NOT_READY); + window->Win_Clear_Status(WIN_STATUS_ALWAYS_COLOR); + CommandAvailability availability = Get_Command_Availability(button, obj, window, nullptr, false); + + switch (availability) { + case COMMAND_AVAILABLITY_UNK0: + window->Win_Enable(false); + break; + case COMMAND_AVAILABLITY_UNK3: + window->Win_Hide(true); + break; + case COMMAND_AVAILABLITY_UNK4: + window->Win_Enable(false); + window->Win_Set_Status(WIN_STATUS_NOT_READY); + break; + case COMMAND_AVAILABLITY_UNK5: + window->Win_Enable(false); + window->Win_Set_Status(WIN_STATUS_ALWAYS_COLOR); + break; + default: + window->Win_Enable(true); + break; + } + + if (button->Get_Command() != GUI_COMMAND_EXIT_CONTAINER) { + Gadget_Button_Draw_Overlay_Image( + window, Calculate_Veterancy_Overlay_For_Thing(*button->Get_Template())); + } + + if ((button->Get_Options() & WIN_STATUS_NO_FOCUS) != 0) { + captainslog_dbgassert((window->Win_Get_Status() & WIN_STATUS_CHECK_LIKE) != 0, + "Update_Context_Command: Error, gadget window for command '%s' is not check-like!", + button->Get_Name().Str()); + + if (availability == COMMAND_AVAILABLITY_UNK2) { + Gadget_Check_Like_Button_Set_Visual_Check(window, true); + } else { + Gadget_Check_Like_Button_Set_Visual_Check(window, false); + } + } + } + } + } + } +} + +int Get_Rappeller_Count(Object *obj) +{ + int count = 0; + + const std::list *list; + + if (obj->Get_Contain() != nullptr) { + list = obj->Get_Contain()->Get_Contained_Items_List(); + } else { + list = nullptr; + } + + if (list != nullptr) { + for (auto it = list->begin(); it != list->end(); it++) { + if ((*it)->Is_KindOf(KINDOF_CAN_RAPPEL)) { + count++; + } + } + } + + return count; +} + +CommandAvailability ControlBar::Get_Command_Availability( + const CommandButton *button, Object *obj, GameWindow *window, GameWindow *window2, bool b) +{ + if (button->Get_Command() == GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT + || button->Get_Command() == GUI_COMMAND_SPECIAL_POWER_CONSTRUCT_FROM_SHORTCUT) { + if (g_thePlayerList != nullptr && g_thePlayerList->Get_Local_Player() != nullptr) { + obj = g_thePlayerList->Get_Local_Player()->Find_Most_Ready_Shortcut_Special_Power_Of_Type( + button->Get_Special_Power()->Get_Type()); + } else { + obj = nullptr; + } + } + + if (window2 == nullptr) { + window2 = window; + } + + if (obj == nullptr) { + return COMMAND_AVAILABLITY_UNK3; + } + + Player *player = obj->Get_Controlling_Player(); + + if (obj->Get_Script_Status(STATUS_ENABLED) || obj->Get_Script_Status(STATUS_POWERED)) { + return COMMAND_AVAILABLITY_UNK3; + } + + if (obj->Get_Disabled_State(DISABLED_TYPE_DISABLED_UNMANNED)) { + return COMMAND_AVAILABLITY_UNK3; + } + + if (obj->Get_Single_Use_Command()) { + return COMMAND_AVAILABLITY_UNK0; + } + + if ((button->Get_Options() & COMMAND_OPTION_MUST_BE_STOPPED) != 0) { + AIUpdateInterface *update = obj->Get_AI_Update_Interface(); + + if (update != nullptr) { + if (update->Is_Moving()) { + return COMMAND_AVAILABLITY_UNK0; + } + } + } + + bool disabled = obj->Is_Disabled(); + + if (disabled && (button->Get_Options() & COMMAND_OPTION_IGNORES_UNDERPOWERED) != 0) { + if (obj->Get_Disabled_State_Bits().Test(DISABLED_TYPE_DISABLED_UNDERPOWERED)) { + if (obj->Get_Disabled_State_Bits().Count() == 1) { + disabled = false; + } + } + } + + GUICommand command = button->Get_Command(); + + if (!disabled || b || command == GUI_COMMAND_SELL || command == GUI_COMMAND_EVACUATE + || command == GUI_COMMAND_EXIT_CONTAINER || command == GUI_COMMAND_BEACON_DELETE + || command == GUI_COMMAND_SET_RALLY_POINT || command == GUI_COMMAND_STOP || command == GUI_COMMAND_SWITCH_WEAPON) { + if ((button->Get_Options() & COMMAND_OPTION_NEED_UPGRADE) != 0) { + const UpgradeTemplate *upgrade = button->Get_Upgrade_Template(); + + if (upgrade != nullptr) { + if (upgrade->Get_Type() != UPGRADE_TYPE_PLAYER) { + if (upgrade->Get_Type() == UPGRADE_TYPE_OBJECT && !obj->Has_Upgrade(upgrade)) { + return COMMAND_AVAILABLITY_UNK0; + } + } else if (!player->Has_Upgrade_Complete(upgrade)) { + return COMMAND_AVAILABLITY_UNK0; + } + } + } + + ProductionUpdateInterface *production = obj->Get_Production_Update_Interface(); + + if (production != nullptr && production->First_Production() != nullptr + && (button->Get_Options() & COMMAND_OPTION_NOT_QUEUEABLE) != 0) { + return COMMAND_AVAILABLITY_UNK0; + } else { + bool b2; + + if (production != nullptr) { + b2 = production->Get_Production_Count() == QUEUE_ENTRY_COUNT; + } else { + b2 = false; + } + + switch (button->Get_Command()) { + case GUI_COMMAND_DOZER_CONSTRUCT: { + const ThingTemplate *thing = *button->Get_Template(); + + if (thing != nullptr + && (thing->Get_Buildable() == BSTATUS_NO + || (thing->Get_Buildable() == BSTATUS_ONLY_AI + && obj->Get_Controlling_Player()->Get_Player_Type() != Player::PLAYER_COMPUTER))) { + return COMMAND_AVAILABLITY_UNK3; + } else if (obj->Is_KindOf(KINDOF_DOZER)) { + DozerAIInterface *dozer = nullptr; + + if (obj->Get_AI_Update_Interface() != nullptr) { + dozer = obj->Get_AI_Update_Interface()->Get_Dozer_AI_Interface(); + captainslog_dbgassert( + dozer != nullptr, "Something KINDOF_DOZER must have a Dozer-like AIUpdate"); + + if (dozer != nullptr) { + if (dozer->Is_Task_Pending(DOZER_TASK_BUILD)) { + return COMMAND_AVAILABLITY_UNK0; + } else if (player->Can_Build(thing)) { + if (player->Can_Afford_Build(thing)) { + return COMMAND_AVAILABLITY_UNK1; + } + + return COMMAND_AVAILABLITY_UNK0; + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } + case GUI_COMMAND_UNIT_BUILD: { + const ThingTemplate *thing = *button->Get_Template(); + + if (thing != nullptr + && (thing->Get_Buildable() == BSTATUS_NO + || (thing->Get_Buildable() == BSTATUS_ONLY_AI + && obj->Get_Controlling_Player()->Get_Player_Type() != Player::PLAYER_COMPUTER))) { + return COMMAND_AVAILABLITY_UNK3; + } else if (b2) { + return COMMAND_AVAILABLITY_UNK0; + } else { + if (player->Can_Build(thing)) { + CanMakeType can_make = g_theBuildAssistant->Can_Make_Unit(obj, thing); + + if (can_make == CAN_MAKE_MAXIMUM_NUMBER || can_make == CAN_MAKE_PARKING_FULL) { + return COMMAND_AVAILABLITY_UNK0; + } else { + if (can_make != CAN_MAKE_NOT_ENOUGH_MONEY) { + return COMMAND_AVAILABLITY_UNK1; + } + + return COMMAND_AVAILABLITY_UNK0; + } + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } + } + case GUI_COMMAND_PLAYER_UPGRADE: { + if (b2) { + return COMMAND_AVAILABLITY_UNK0; + } else { + if (player->Has_Upgrade_Complete(button->Get_Upgrade_Template()) + || player->Has_Upgrade_In_Production(button->Get_Upgrade_Template())) { + return COMMAND_AVAILABLITY_UNK5; + } else { + if (g_theUpgradeCenter->Can_Afford_Upgrade(player, button->Get_Upgrade_Template(), false)) { + for (unsigned int i = 0; i < button->Get_Sciences()->size(); i++) { + if (!player->Has_Science((*button->Get_Sciences())[i])) { + break; + } + } + + return COMMAND_AVAILABLITY_UNK1; + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } + } + } + case GUI_COMMAND_OBJECT_UPGRADE: { + if (b2) { + return COMMAND_AVAILABLITY_UNK0; + } else if (production != nullptr) { + if (obj->Has_Upgrade(button->Get_Upgrade_Template()) + || production->Is_Upgrade_In_Queue(button->Get_Upgrade_Template()) + || !obj->Affected_By_Upgrade(button->Get_Upgrade_Template())) { + return COMMAND_AVAILABLITY_UNK5; + } else { + if (g_theUpgradeCenter->Can_Afford_Upgrade(player, button->Get_Upgrade_Template(), false)) { + for (unsigned int i = 0;; i++) { + + if (i >= button->Get_Sciences()->size()) { + return COMMAND_AVAILABLITY_UNK1; + } + + if (!player->Has_Science((*button->Get_Sciences())[i])) { + break; + } + } + + return COMMAND_AVAILABLITY_UNK0; + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } + } else { + captainslog_dbgassert( + false, "Objects that have Object-Level Upgrades must also have ProductionUpdate. Just cuz."); + return COMMAND_AVAILABLITY_UNK0; + } + } + case GUI_COMMAND_STOP: { + if ((button->Get_Options() & COMMAND_OPTION_OPTION_ONE) != 0) { + static NameKeyType key_BattlePlanUpdate = g_theNameKeyGenerator->Name_To_Key("BattlePlanUpdate"); + BattlePlanUpdate *plan = + static_cast(obj->Find_Update_Module(key_BattlePlanUpdate)); + + if (plan == nullptr || plan->Get_Active_Battle_Plan() == BATTLE_PLAN_STATUS_BOMBARDMENT) { + return COMMAND_AVAILABLITY_UNK1; + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } else { + return COMMAND_AVAILABLITY_UNK1; + } + } + case GUI_COMMAND_EXIT_CONTAINER: { + if (!obj->Get_Disabled_State(DISABLED_TYPE_DISABLED_SUBDUED)) { + return COMMAND_AVAILABLITY_UNK1; + } + + return COMMAND_AVAILABLITY_UNK0; + } + case GUI_COMMAND_EVACUATE: { + if (obj->Get_Contain() != nullptr && obj->Get_Contain()->Get_Contain_Count() != 0) { + if (!obj->Get_Disabled_State(DISABLED_TYPE_DISABLED_SUBDUED)) { + return COMMAND_AVAILABLITY_UNK1; + } + + return COMMAND_AVAILABLITY_UNK0; + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } + case GUI_COMMAND_EXECUTE_RAILED_TRANSPORT: { + DockUpdateInterface *dock = obj->Get_Dock_Update_Interface(); + + if (dock != nullptr && dock->Is_Dock_Open()) { + return COMMAND_AVAILABLITY_UNK1; + } + + return COMMAND_AVAILABLITY_UNK0; + } + case GUI_COMMAND_SELL: { + if (obj->Get_Script_Status(STATUS_UNSELLABLE)) { + return COMMAND_AVAILABLITY_UNK3; + } else { + if (!obj->Get_Disabled_State(DISABLED_TYPE_DISABLED_SUBDUED)) { + return COMMAND_AVAILABLITY_UNK1; + } + + return COMMAND_AVAILABLITY_UNK0; + } + } + case GUI_COMMAND_FIRE_WEAPON: { + if (obj->Get_AI_Update_Interface() != nullptr) { + const Weapon *weapon = obj->Get_Weapon_In_Weapon_Slot(button->Get_Weapon_Slot()); + unsigned int frame = g_theGameLogic->Get_Frame(); + + if (weapon == nullptr || weapon->Get_Clip_Reload_Time(obj) != 0) { + if (weapon != nullptr) { + if (weapon->Get_Status() == Weapon::READY_TO_FIRE) { + if (weapon->Get_Next_Shot() != frame) { + if (weapon->Get_Next_Shot() != frame - 1) { + return COMMAND_AVAILABLITY_UNK1; + } + } + } + } + + if (weapon != nullptr) { + if (weapon->Get_Status() == Weapon::RELOADING_CLIP) { + Gadget_Button_Draw_Inverse_Clock( + window2, weapon->Get_Percent_Ready_To_Fire() * 100.0f, m_buildUpClockColor); + } + + return COMMAND_AVAILABLITY_UNK4; + } else { + if ((button->Get_Options() & COMMAND_OPTION_USES_MINE_CLEARING_WEAPONSET) != 0 + && obj->Test_Weapon_Set_Flag(WEAPONSET_MINE_CLEARING_DETAIL)) { + return COMMAND_AVAILABLITY_UNK1; + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } + } else { + return COMMAND_AVAILABLITY_UNK1; + } + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } + case GUI_COMMAND_SPECIAL_POWER: + case GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT: + case GUI_COMMAND_SPECIAL_POWER_CONSTRUCT: + case GUI_COMMAND_SPECIAL_POWER_CONSTRUCT_FROM_SHORTCUT: { + captainslog_dbgassert(button->Get_Special_Power() != nullptr, + "The special power in the command '%s' is NULL", + button->Get_Name().Str()); + SpecialPowerModuleInterface *power = obj->Get_Special_Power_Module(button->Get_Special_Power()); + + if (power == nullptr) { + captainslog_dbgassert(false, + "Object %s does not contain special power module (%s) to execute. Did you forget to add it to " + "the object INI?", + obj->Get_Template()->Get_Name().Str(), + button->Get_Special_Power()->Get_Name().Str()); + return COMMAND_AVAILABLITY_UNK1; + } + + if (power->Is_Ready()) { + SpecialAbilityUpdate *ability = + obj->Find_Special_Ability_Update(button->Get_Special_Power()->Get_Type()); + + if (ability != nullptr) { + if (!ability->Is_Power_Currently_In_Use(button)) { + return COMMAND_AVAILABLITY_UNK1; + } + + return COMMAND_AVAILABLITY_UNK0; + } else { + if (power->Get_Special_Power_Template()->Get_Type() != SPECIAL_CHANGE_BATTLE_PLANS) { + return COMMAND_AVAILABLITY_UNK1; + } + + static NameKeyType key_BattlePlanUpdate = g_theNameKeyGenerator->Name_To_Key("BattlePlanUpdate"); + BattlePlanUpdate *plan = + static_cast(obj->Find_Update_Module(key_BattlePlanUpdate)); + + if (plan == nullptr) { + return COMMAND_AVAILABLITY_UNK1; + } + + if ((button->Get_Options() & plan->Get_Command_Option()) == 0) { + return COMMAND_AVAILABLITY_UNK1; + } + + return COMMAND_AVAILABLITY_UNK2; + } + } else { + Gadget_Button_Draw_Inverse_Clock(window2, power->Get_Percent_Ready() * 100.0f, m_buildUpClockColor); + return COMMAND_AVAILABLITY_UNK4; + } + } + case GUI_COMMAND_HACK_INTERNET: { + const AIUpdateInterface *update = obj->Get_AI_Update_Interface(); + + if (update != nullptr) { + const HackInternetAIInterface *hack = update->Get_Hack_Internet_AI_Interface(); + + if (hack != nullptr) { + if (hack->Is_Hacking_Packing_Or_Unpacking()) { + return COMMAND_AVAILABLITY_UNK0; + } + } + + return COMMAND_AVAILABLITY_UNK1; + } + } + case GUI_COMMAND_TOGGLE_OVERCHARGE: { + for (BehaviorModule **module = obj->Get_All_Modules(); *module != nullptr; module++) { + OverchargeBehaviorInterface *overcharge = (*module)->Get_Overcharge_Behavior_Interface(); + + if (overcharge != nullptr) { + if (overcharge->Is_Overcharge_Active()) { + return COMMAND_AVAILABLITY_UNK2; + } + } + } + + return COMMAND_AVAILABLITY_UNK1; + } + case GUI_COMMAND_COMBATDROP: { + if (Get_Rappeller_Count(obj) > 0) { + return COMMAND_AVAILABLITY_UNK1; + } + + return COMMAND_AVAILABLITY_UNK0; + } + case GUI_COMMAND_SWITCH_WEAPON: { + const Weapon *weapon = obj->Get_Weapon_In_Weapon_Slot(button->Get_Weapon_Slot()); + captainslog_dbgassert(weapon != nullptr, + "Unit %s's CommandButton %s is trying to access weaponslot %d, but doesn't have a weapon there in " + "its FactionUnit ini entry.", + obj->Get_Template()->Get_Name().Str(), + button->Get_Name().Str(), + button->Get_Weapon_Slot()); + + if (weapon != nullptr) { + const std::list *drawables = g_theInGameUI->Get_All_Selected_Drawables(); + + for (auto it = drawables->begin(); it != drawables->end(); it++) { + Drawable *drawable = *it; + + if (drawable != nullptr) { + if (drawable->Get_Object() != nullptr) { + if (drawable->Get_Object()->Is_Locally_Controlled()) { + if (drawable->Get_Object()->Get_Current_Weapon(nullptr) != nullptr) { + if (drawable->Get_Object()->Get_Current_Weapon(nullptr)->Get_Weapon_Slot() + != button->Get_Weapon_Slot()) { + return COMMAND_AVAILABLITY_UNK1; + } + } + } + } + } + } + + return COMMAND_AVAILABLITY_UNK2; + } else { + return COMMAND_AVAILABLITY_UNK0; + } + } + case GUI_COMMAND_SELECT_ALL_UNITS_OF_TYPE: { + return COMMAND_AVAILABLITY_UNK1; + } + default: { + return COMMAND_AVAILABLITY_UNK1; + } + } + } + } else if (Get_Command_Availability(button, obj, window, window2, true) == COMMAND_AVAILABLITY_UNK3) { + return COMMAND_AVAILABLITY_UNK3; + } else { + return COMMAND_AVAILABLITY_UNK0; + } } diff --git a/src/game/client/gui/controlbar/controlbarcommandprocessing.cpp b/src/game/client/gui/controlbar/controlbarcommandprocessing.cpp index 59a9f9576..8e9876e59 100644 --- a/src/game/client/gui/controlbar/controlbarcommandprocessing.cpp +++ b/src/game/client/gui/controlbar/controlbarcommandprocessing.cpp @@ -294,7 +294,7 @@ CBCommandStatus ControlBar::Process_Command_UI(GameWindow *control, GadgetGameMe if (i == 9) { captainslog_dbgassert(false, "Control not found in build queue data"); } else if (m_queueData[i].type == ProductionEntry::PRODUCTION_UPGRADE) { - UpgradeTemplate *upgrade = m_queueData[i].upgrade_template; + const UpgradeTemplate *upgrade = m_queueData[i].upgrade_template; if (upgrade != nullptr) { if (obj != nullptr) { @@ -540,3 +540,17 @@ CBCommandStatus ControlBar::Process_Command_UI(GameWindow *control, GadgetGameMe return CBC_COMMAND_NOT_USED; } } + +CBCommandStatus ControlBar::Process_Command_Transition_UI(GameWindow *control, GadgetGameMessage gadget_message) +{ + if (m_currContext == CB_CONTEXT_MULTI_SELECT + || (m_currentSelectedDrawable != nullptr && m_currentSelectedDrawable->Get_Object())) { + return CBC_COMMAND_USED; + } + + if (m_currContext != CB_CONTEXT_NONE && m_currContext != CB_CONTEXT_UNK && m_currContext != CB_CONTEXT_OBSERVER) { + Switch_To_Context(CB_CONTEXT_NONE, nullptr); + } + + return CBC_COMMAND_NOT_USED; +} diff --git a/src/game/client/gui/controlbar/controlbarmultiselect.cpp b/src/game/client/gui/controlbar/controlbarmultiselect.cpp index d5e8f80d9..2c5f94c2e 100644 --- a/src/game/client/gui/controlbar/controlbarmultiselect.cpp +++ b/src/game/client/gui/controlbar/controlbarmultiselect.cpp @@ -13,10 +13,194 @@ * LICENSE */ #include "controlbar.h" +#include "gadgetpushbutton.h" + +void ControlBar::Reset_Common_Command_Data() +{ + for (int i = 0; i < CommandSet::MAX_COMMAND_BUTTONS; i++) { + m_commonCommands[i] = nullptr; + Gadget_Button_Draw_Overlay_Image(m_commandWindows[i], nullptr); + } +} + +void ControlBar::Add_Common_Commands(Drawable *draw, bool first_drawable) +{ + if (draw != nullptr) { + Object *obj = draw->Get_Object(); + + if (obj != nullptr) { + if (!obj->Is_KindOf(KINDOF_IGNORED_IN_GUI)) { + const CommandSet *set = Find_Command_Set(obj->Get_Command_Set_String()); + + if (set != nullptr) { + if (first_drawable) { + for (int i = 0; i < CommandSet::MAX_COMMAND_BUTTONS; i++) { + if (m_commandWindows[i] != nullptr) { + const CommandButton *button = set->Get_Command_Button(i); + + if (button != nullptr) { + if ((button->Get_Options() & COMMAND_OPTION_OK_FOR_MULTI_SELECT) != 0) { + m_commonCommands[i] = button; + m_commandWindows[i]->Win_Hide(false); + m_commandWindows[i]->Win_Enable(true); + Set_Control_Command(m_commandWindows[i], button); + } + } + } + } + } else { + for (int i = 0; i < CommandSet::MAX_COMMAND_BUTTONS; i++) { + if (m_commandWindows[i] != nullptr) { + const CommandButton *button = set->Get_Command_Button(i); + bool is_attack_move = (button != nullptr && button->Get_Command() == GUI_COMMAND_ATTACK_MOVE) + || (m_commonCommands[i] != nullptr + && m_commonCommands[i]->Get_Command() == GUI_COMMAND_ATTACK_MOVE); + + if (is_attack_move && m_commonCommands[i] == nullptr) { + m_commonCommands[i] = button; + m_commandWindows[i]->Win_Hide(false); + m_commandWindows[i]->Win_Enable(true); + Set_Control_Command(m_commandWindows[i], button); + } else if (button != m_commonCommands[i] && !is_attack_move) { + m_commonCommands[i] = nullptr; + m_commandWindows[i]->Win_Hide(true); + } + } + } + } + } else { + for (int i = 0; i < CommandSet::MAX_COMMAND_BUTTONS; i++) { + m_commonCommands[i] = nullptr; + + if (m_commandWindows[i] != nullptr) { + m_commandWindows[i]->Win_Hide(true); + } + } + } + } + } + } +} + +void ControlBar::Populate_Multi_Select() +{ + bool first_drawable = true; + bool check_image = false; + const Image *image = nullptr; + Object *obj = nullptr; + Reset_Common_Command_Data(); + + for (int i = 0; i < CommandSet::MAX_COMMAND_BUTTONS; i++) { + if (m_commandWindows[i] != nullptr) { + m_commandWindows[i]->Win_Hide(true); + } + } + + captainslog_dbgassert(g_theInGameUI->Get_Select_Count() > 1, + "Populate_Multi_Select: Can't populate multiselect context cause there are only '%d' things selected", + g_theInGameUI->Get_Select_Count()); + const std::list *drawables = g_theInGameUI->Get_All_Selected_Drawables(); + captainslog_dbgassert(!drawables->empty(), "Populate_Multi_Select: Drawable list is empty"); + + for (auto it = drawables->begin(); it != drawables->end(); it++) { + Drawable *drawable = *it; + + if (!drawable->Get_Object()->Is_KindOf(KINDOF_IGNORED_IN_GUI)) { + if (drawable != nullptr) { + if (drawable->Get_Object() != nullptr) { + if (!drawable->Get_Object()->Get_Status_Bits().Test(OBJECT_STATUS_SOLD)) { + Add_Common_Commands(drawable, first_drawable); + first_drawable = false; + + if (!check_image) { + image = drawable->Get_Template()->Get_Selected_Portrait_Image(); + obj = drawable->Get_Object(); + check_image = true; + } else if (drawable->Get_Template()->Get_Selected_Portrait_Image() != image) { + image = nullptr; + } + } + } + } + } + } + + Set_Portrait_By_Object(obj); +} void ControlBar::Update_Context_Multi_Select() { -#ifdef GAME_DLL - Call_Method(PICK_ADDRESS(0x005AB940, 0x008F4155), this); -#endif + int count[CommandSet::MAX_COMMAND_BUTTONS]; + memset(count, 0, sizeof(count)); + captainslog_dbgassert(g_theInGameUI->Get_Select_Count() > 1, + "Update_Context_Multi_Select: TheInGameUI only has '%d' things selected", + g_theInGameUI->Get_Select_Count()); + const std::list *drawables = g_theInGameUI->Get_All_Selected_Drawables(); + captainslog_dbgassert(!drawables->empty(), "Populate_Multi_Select: Drawable list is empty"); + + for (auto it = drawables->begin(); it != drawables->end(); it++) { + Drawable *drawable = *it; + + if (!drawable->Get_Object()->Is_KindOf(KINDOF_IGNORED_IN_GUI)) { + Object *obj = drawable->Get_Object(); + + if (obj != nullptr) { + for (int i = 0; i < CommandSet::MAX_COMMAND_BUTTONS; i++) { + GameWindow *window = m_commandWindows[i]; + + if (window != nullptr) { + if (!window->Win_Is_Hidden()) { + CommandButton *button = static_cast(Gadget_Button_Get_Data(window)); + + if (button != nullptr) { + CommandAvailability availability = + Get_Command_Availability(button, obj, window, nullptr, false); + window->Win_Clear_Status(COMMAND_OPTION_CAN_USE_WAYPOINTS); + window->Win_Clear_Status(WIN_STATUS_ALWAYS_COLOR); + + switch (availability) { + case COMMAND_AVAILABLITY_UNK0: + window->Win_Enable(false); + break; + case COMMAND_AVAILABLITY_UNK3: + window->Win_Hide(true); + break; + case COMMAND_AVAILABLITY_UNK4: + window->Win_Enable(false); + window->Win_Set_Status(WIN_STATUS_NOT_READY); + break; + case COMMAND_AVAILABLITY_UNK5: + window->Win_Enable(false); + window->Win_Set_Status(WIN_STATUS_ALWAYS_COLOR); + break; + default: + window->Win_Enable(true); + break; + } + + if ((button->Get_Options() & COMMAND_OPTION_CHECK_LIKE) != 0) { + Gadget_Check_Like_Button_Set_Visual_Check( + window, availability == COMMAND_AVAILABLITY_UNK2); + } + + if (availability == COMMAND_AVAILABLITY_UNK1 || availability == COMMAND_AVAILABLITY_UNK2) { + count[i]++; + } + } + } + } + } + } + } + } + + for (int i = 0; i < CommandSet::MAX_COMMAND_BUTTONS; i++) { + if (m_commandWindows[i] != nullptr && !m_commandWindows[i]->Win_Is_Hidden() && m_commonCommands[i] != nullptr) { + if (count[i] <= 0) { + m_commandWindows[i]->Win_Enable(false); + } else { + m_commandWindows[i]->Win_Enable(true); + } + } + } } diff --git a/src/game/client/gui/controlbar/controlbarresizer.cpp b/src/game/client/gui/controlbar/controlbarresizer.cpp index 39984ad88..5da102d75 100644 --- a/src/game/client/gui/controlbar/controlbarresizer.cpp +++ b/src/game/client/gui/controlbar/controlbarresizer.cpp @@ -13,3 +13,6 @@ * LICENSE */ #include "controlbar.h" +#include "ini.h" + +// ResizerWindow and ControlBarResizer classes unused diff --git a/src/game/client/gui/controlbar/controlbarscheme.cpp b/src/game/client/gui/controlbar/controlbarscheme.cpp index ef08fbc87..dae957974 100644 --- a/src/game/client/gui/controlbar/controlbarscheme.cpp +++ b/src/game/client/gui/controlbar/controlbarscheme.cpp @@ -13,22 +13,498 @@ * LICENSE */ #include "controlbarscheme.h" +#include "colorspace.h" +#include "controlbar.h" +#include "display.h" +#include "gadgetpushbutton.h" +#include "gamewindowmanager.h" +#include "player.h" +#include "playertemplate.h" +#include "recorder.h" + +ControlBarSchemeImage::ControlBarSchemeImage() : m_image(nullptr), m_layer(0) +{ + m_position.x = 0; + m_position.y = 0; + m_size.x = 0; + m_size.y = 0; +} ControlBarSchemeImage::~ControlBarSchemeImage() { m_image = nullptr; } +ControlBarSchemeAnimation::ControlBarSchemeAnimation() : + m_animType(0), m_animImage(nullptr), m_animDuration(0), m_currentFrame(0) +{ + m_finalPos.x = 0; + m_finalPos.y = 0; + m_startPos.x = 0; + m_startPos.y = 0; +} + ControlBarSchemeAnimation::~ControlBarSchemeAnimation() { m_animImage = nullptr; } +ControlBarScheme::ControlBarScheme() : + m_buttonQueueImage(nullptr), + m_rightHUDImage(nullptr), + m_buildUpClockColor(Make_Color(0, 0, 0, 100)), + m_borderBuildColor(0xFFFFFFFF), + m_borderActionColor(0xFFFFFFFF), + m_borderUpgradeColor(0xFFFFFFFF), + m_borderSystemColor(0xFFFFFFFF), + m_commandBarBorderColor(0), + m_optionsButtonEnableImage(nullptr), + m_optionsButtonHilitedImage(nullptr), + m_optionsButtonPushedImage(nullptr), + m_optionsButtonDisabledImage(nullptr), + m_idleWorkerButtonEnableImage(nullptr), + m_idleWorkerButtonHilitedImage(nullptr), + m_idleWorkerButtonPushedImage(nullptr), + m_idleWorkerButtonDisabledImage(nullptr), + m_buddyButtonEnableImage(nullptr), + m_buddyButtonHilitedImage(nullptr), + m_buddyButtonPushedImage(nullptr), + m_buddyButtonDisabledImage(nullptr), + m_beaconButtonEnableImage(nullptr), + m_beaconButtonHilitedImage(nullptr), + m_beaconButtonPushedImage(nullptr), + m_beaconButtonDisabledImage(nullptr), + m_genBarButtonInImage(nullptr), + m_genBarButtonOnImage(nullptr), + m_toggleButtonUpInImage(nullptr), + m_toggleButtonUpOnImage(nullptr), + m_toggleButtonUpPushedImage(nullptr), + m_toggleButtonDownInImage(nullptr), + m_toggleButtonDownOnImage(nullptr), + m_toggleButtonDownPushedImage(nullptr), + m_generalButtonEnableImage(nullptr), + m_generalButtonHilitedImage(nullptr), + m_generalButtonPushedImage(nullptr), + m_generalButtonDisabledImage(nullptr), + m_uAttackButtonEnableImage(nullptr), + m_uAttackButtonHilitedImage(nullptr), + m_uAttackButtonPushedImage(nullptr), + m_minMaxButtonEnableImage(nullptr), + m_minMaxButtonHilitedImage(nullptr), + m_minMaxButtonPushedImage(nullptr), + m_genArrowImage(nullptr), + m_expBarForegroundImage(nullptr), + m_commandMarkerImage(nullptr), + m_powerPurchaseImage(nullptr) +{ + m_screenCreationRes.x = 0; + m_screenCreationRes.y = 0; + m_minMaxUL.x = 0; + m_minMaxLR.x = 0; + m_generalUL.x = 0; + m_generalLR.x = 0; + m_uAttackUL.x = 0; + m_uAttackLR.x = 0; + m_optionsUL.x = 0; + m_optionsLR.x = 0; + m_workerUL.x = 0; + m_workerLR.x = 0; + m_chatUL.x = 0; + m_chatLR.x = 0; + m_beaconUL.x = 0; + m_beaconLR.x = 0; + m_powerBarUL.x = 0; + m_powerBarLR.x = 0; + m_moneyUL.x = 0; + m_moneyLR.x = 0; + m_minMaxUL.y = 0; + m_minMaxLR.y = 0; + m_generalUL.y = 0; + m_generalLR.y = 0; + m_uAttackUL.y = 0; + m_uAttackLR.y = 0; + m_optionsUL.y = 0; + m_optionsLR.y = 0; + m_workerUL.y = 0; + m_workerLR.y = 0; + m_chatUL.y = 0; + m_chatLR.y = 0; + m_beaconUL.y = 0; + m_beaconLR.y = 0; + m_powerBarUL.y = 0; + m_powerBarLR.y = 0; + m_moneyUL.y = 0; + m_moneyLR.y = 0; +} + ControlBarScheme::~ControlBarScheme() { Reset(); } +void ControlBarScheme::Init() +{ + if (g_theControlBar != nullptr) { + g_theControlBar->Switch_Control_Bar_Stage(CONTROL_BAR_STAGE_DEFAULT); + g_theControlBar->Update_Build_Queue_Disabled_Images(m_buttonQueueImage); + g_theControlBar->Update_Right_HUD_Image(m_rightHUDImage); + g_theControlBar->Update_Build_Up_Clock_Color(m_buildUpClockColor); + g_theControlBar->Update_Command_Bar_Border_Colors( + m_borderBuildColor, m_borderActionColor, m_borderUpgradeColor, m_borderSystemColor); + g_theControlBar->Set_Command_Bar_Border_Color(m_commandBarBorderColor); + g_theControlBar->Update_Slot_Exit_Image(m_commandMarkerImage); + g_theControlBar->Update_Up_Down_Images(m_toggleButtonUpInImage, + m_toggleButtonUpOnImage, + m_toggleButtonUpPushedImage, + m_toggleButtonDownInImage, + m_toggleButtonDownOnImage, + m_toggleButtonDownPushedImage, + m_generalButtonEnableImage, + m_generalButtonHilitedImage); + g_theControlBar->Set_Gen_Arrow_Image(m_genArrowImage); + } + + GameWindow *window = nullptr; + float width = (float)g_theDisplay->Get_Width() / (float)m_screenCreationRes.x; + float height = (float)g_theDisplay->Get_Height() / (float)m_screenCreationRes.y; + window = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:PopupCommunicator")); + + if (window != nullptr) { + Gadget_Button_Set_Enabled_Image(window, m_buddyButtonEnableImage); + Gadget_Button_Set_Hilite_Image(window, m_buddyButtonHilitedImage); + Gadget_Button_Set_Hilite_Selected_Image(window, m_buddyButtonPushedImage); + Gadget_Button_Set_Disabled_Image(window, m_buddyButtonDisabledImage); + + GameWindow *parent = window->Win_Get_Parent(); + int x_pos; + int y_pos; + + if (parent != nullptr) { + int parent_x; + int parent_y; + parent->Win_Get_Screen_Position(&parent_x, &parent_y); + x_pos = (float)m_chatUL.x * width - (float)parent_x; + y_pos = (float)m_chatUL.y * height - (float)parent_y; + } else { + x_pos = (float)m_chatUL.x * width; + y_pos = (float)m_chatUL.y * height; + } + + window->Win_Set_Position(x_pos, y_pos); + window->Win_Set_Size( + (float)(m_chatLR.x - m_chatUL.x) * width + 0.0f, (float)(m_chatLR.y - m_chatUL.y) * height + 0.0f); + } + + window = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:ButtonIdleWorker")); + + if (window != nullptr) { + Gadget_Button_Set_Enabled_Image(window, m_idleWorkerButtonEnableImage); + Gadget_Button_Set_Hilite_Image(window, m_idleWorkerButtonHilitedImage); + Gadget_Button_Set_Hilite_Selected_Image(window, m_idleWorkerButtonPushedImage); + Gadget_Button_Set_Disabled_Image(window, m_idleWorkerButtonDisabledImage); + + GameWindow *parent = window->Win_Get_Parent(); + int x_pos; + int y_pos; + + if (parent != nullptr) { + int parent_x; + int parent_y; + parent->Win_Get_Screen_Position(&parent_x, &parent_y); + x_pos = (float)m_workerUL.x * width - (float)parent_x; + y_pos = (float)m_workerUL.y * height - (float)parent_y; + } else { + x_pos = (float)m_workerUL.x * width; + y_pos = (float)m_workerUL.y * height; + } + + window->Win_Set_Position(x_pos, y_pos); + window->Win_Set_Size( + (float)(m_workerLR.x - m_workerUL.x) * width + 0.0f, (float)(m_workerLR.y - m_workerUL.y) * height + 0.0f); + } + + window = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:ExpBarForeground")); + + if (window != nullptr) { + window->Win_Set_Enabled_Image(0, m_expBarForegroundImage); + } + + window = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:ButtonOptions")); + + if (window != nullptr) { + Gadget_Button_Set_Enabled_Image(window, m_optionsButtonEnableImage); + Gadget_Button_Set_Hilite_Image(window, m_optionsButtonHilitedImage); + Gadget_Button_Set_Hilite_Selected_Image(window, m_optionsButtonPushedImage); + Gadget_Button_Set_Disabled_Image(window, m_optionsButtonDisabledImage); + + GameWindow *parent = window->Win_Get_Parent(); + int x_pos; + int y_pos; + + if (parent != nullptr) { + int parent_x; + int parent_y; + parent->Win_Get_Screen_Position(&parent_x, &parent_y); + x_pos = (float)m_optionsUL.x * width - (float)parent_x; + y_pos = (float)m_optionsUL.y * height - (float)parent_y; + } else { + x_pos = (float)m_optionsUL.x * width; + y_pos = (float)m_optionsUL.y * height; + } + + window->Win_Set_Position(x_pos, y_pos); + window->Win_Set_Size( + (float)(m_optionsLR.x - m_optionsUL.x) * width + 0.0f, (float)(m_optionsLR.y - m_optionsUL.y) * height + 0.0f); + } + + window = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:ButtonPlaceBeacon")); + + if (window != nullptr) { + Gadget_Button_Set_Enabled_Image(window, m_beaconButtonEnableImage); + Gadget_Button_Set_Hilite_Image(window, m_beaconButtonHilitedImage); + Gadget_Button_Set_Hilite_Selected_Image(window, m_beaconButtonPushedImage); + Gadget_Button_Set_Disabled_Image(window, m_beaconButtonDisabledImage); + + GameWindow *parent = window->Win_Get_Parent(); + int x_pos; + int y_pos; + + if (parent != nullptr) { + int parent_x; + int parent_y; + parent->Win_Get_Screen_Position(&parent_x, &parent_y); + x_pos = (float)m_beaconUL.x * width - (float)parent_x; + y_pos = (float)m_beaconUL.y * height - (float)parent_y; + } else { + x_pos = (float)m_beaconUL.x * width; + y_pos = (float)m_beaconUL.y * height; + } + + window->Win_Set_Position(x_pos, y_pos); + window->Win_Set_Size( + (float)(m_beaconLR.x - m_beaconUL.x) * width + 0.0f, (float)(m_beaconLR.y - m_beaconUL.y) * height + 0.0f); + } + + window = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:MoneyDisplay")); + + if (window != nullptr) { + GameWindow *parent = window->Win_Get_Parent(); + int x_pos; + int y_pos; + + if (parent != nullptr) { + int parent_x; + int parent_y; + parent->Win_Get_Screen_Position(&parent_x, &parent_y); + x_pos = (float)m_moneyUL.x * width - (float)parent_x; + y_pos = (float)m_moneyUL.y * height - (float)parent_y; + } else { + x_pos = (float)m_moneyUL.x * width; + y_pos = (float)m_moneyUL.y * height; + } + + window->Win_Set_Position(x_pos, y_pos); + window->Win_Set_Size( + (float)(m_moneyLR.x - m_moneyUL.x) * width + 0.0f, (float)(m_moneyLR.y - m_moneyUL.y) * height + 0.0f); + } + + window = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:PowerWindow")); + + if (window != nullptr) { + GameWindow *parent = window->Win_Get_Parent(); + int x_pos; + int y_pos; + + if (parent != nullptr) { + int parent_x; + int parent_y; + parent->Win_Get_Screen_Position(&parent_x, &parent_y); + x_pos = (float)m_powerBarUL.x * width - (float)parent_x; + y_pos = (float)m_powerBarUL.y * height - (float)parent_y; + } else { + x_pos = (float)m_powerBarUL.x * width; + y_pos = (float)m_powerBarUL.y * height; + } + + window->Win_Set_Position(x_pos, y_pos); + window->Win_Set_Size((float)(m_powerBarLR.x - m_powerBarUL.x) * width + 0.0f, + (float)(m_powerBarLR.y - m_powerBarUL.y) * height + 0.0f); + } + + window = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:ButtonGeneral")); + + if (window != nullptr) { + Gadget_Button_Set_Enabled_Image(window, m_generalButtonEnableImage); + Gadget_Button_Set_Hilite_Image(window, m_generalButtonHilitedImage); + Gadget_Button_Set_Hilite_Selected_Image(window, m_generalButtonPushedImage); + Gadget_Button_Set_Disabled_Image(window, m_generalButtonDisabledImage); + + GameWindow *parent = window->Win_Get_Parent(); + int x_pos; + int y_pos; + + if (parent != nullptr) { + int parent_x; + int parent_y; + parent->Win_Get_Screen_Position(&parent_x, &parent_y); + x_pos = (float)m_generalUL.x * width - (float)parent_x; + y_pos = (float)m_generalUL.y * height - (float)parent_y; + } else { + x_pos = (float)m_generalUL.x * width; + y_pos = (float)m_generalUL.y * height; + } + + window->Win_Set_Position(x_pos, y_pos); + window->Win_Set_Size( + (float)(m_generalLR.x - m_generalUL.x) * width + 0.0f, (float)(m_generalLR.y - m_generalUL.y) * height + 0.0f); + } + + window = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:ButtonLarge")); + + if (window != nullptr) { + GameWindow *parent = window->Win_Get_Parent(); + int x_pos; + int y_pos; + + if (parent != nullptr) { + int parent_x; + int parent_y; + parent->Win_Get_Screen_Position(&parent_x, &parent_y); + x_pos = (float)m_minMaxUL.x * width - (float)parent_x; + y_pos = (float)m_minMaxUL.y * height - (float)parent_y; + } else { + x_pos = (float)m_minMaxUL.x * width; + y_pos = (float)m_minMaxUL.y * height; + } + + window->Win_Set_Position(x_pos, y_pos); + window->Win_Set_Size( + (float)(m_minMaxLR.x - m_minMaxUL.x) * width + 0.0f, (float)(m_minMaxLR.y - m_minMaxUL.y) * height + 0.0f); + } + + window = + g_theWindowManager->Win_Get_Window_From_Id(nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:WinUAttack")); + + if (window != nullptr) { + window->Win_Set_Enabled_Image(0, m_uAttackButtonEnableImage); + window->Win_Set_Disabled_Image(0, m_uAttackButtonHilitedImage); + + GameWindow *parent = window->Win_Get_Parent(); + int x_pos; + int y_pos; + + if (parent != nullptr) { + int parent_x; + int parent_y; + parent->Win_Get_Screen_Position(&parent_x, &parent_y); + x_pos = (float)m_uAttackUL.x * width - (float)parent_x; + y_pos = (float)m_uAttackUL.y * height - (float)parent_y; + } else { + x_pos = (float)m_uAttackUL.x * width; + y_pos = (float)m_uAttackUL.y * height; + } + + window->Win_Set_Position(x_pos, y_pos); + window->Win_Set_Size( + (float)(m_uAttackLR.x - m_uAttackUL.x) * width + 0.0f, (float)(m_uAttackLR.y - m_uAttackUL.y) * height + 0.0f); + } + + window = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("GeneralsExpPoints.wnd:GenExpParent")); + + if (window != nullptr) { + window->Win_Set_Enabled_Image(0, m_powerPurchaseImage); + + if (m_powerPurchaseImage != nullptr) { + window->Win_Set_Size( + m_powerPurchaseImage->Get_Image_Width() * width, m_powerPurchaseImage->Get_Image_Height() * height); + } + } +} + +void ControlBarScheme::Add_Animation(ControlBarSchemeAnimation *scheme_anim) +{ + if (scheme_anim != nullptr) { + m_animations.push_back(scheme_anim); + } else { + captainslog_dbgassert(false, "Trying to add a null animation to the controlbarscheme"); + } +} + +void ControlBarScheme::Add_Image(ControlBarSchemeImage *scheme_image) +{ + if (scheme_image != nullptr) { + if (scheme_image->m_layer >= LAYER_COUNT) { + captainslog_dbgassert(false, + "SchemeImage %s attempted to be added to layer %d which is not between %d, %d", + scheme_image->m_name.Str(), + scheme_image->m_layer, + 0, + LAYER_COUNT); + scheme_image->m_layer = 0; + } + + m_layer[scheme_image->m_layer].push_back(scheme_image); + } else { + captainslog_dbgassert(false, "Trying to add a null image to the controlbarscheme"); + } +} + +void ControlBarScheme::Draw_Background(Coord2D multi, ICoord2D offset) +{ + for (int i = 5; i >= 3; i--) { + for (auto it = m_layer[i].begin(); it != m_layer[i].end(); it++) { + ControlBarSchemeImage *image = *it; + + if (image != nullptr) { + if (image->m_image != nullptr) { + g_theDisplay->Draw_Image(image->m_image, + (float)image->m_position.x * multi.x + (float)offset.x, + (float)image->m_position.y * multi.y + (float)offset.y, + (float)(image->m_size.x + image->m_position.x) * multi.x + (float)offset.x, + (float)(image->m_size.y + image->m_position.y) * multi.y + (float)offset.y, + 0xFFFFFFFF, + Display::DRAWIMAGE_ADDITIVE); + } + } else { + captainslog_dbgassert(false, "There is no ControlBarSchemeImage found in the m_layer list"); + } + } + } +} + +void ControlBarScheme::Draw_Foreground(Coord2D multi, ICoord2D offset) +{ + for (int i = 2; i >= 0; i--) { + for (auto it = m_layer[i].begin(); it != m_layer[i].end(); it++) { + ControlBarSchemeImage *image = *it; + + if (image != nullptr) { + if (image->m_image != nullptr) { + g_theDisplay->Draw_Image(image->m_image, + (float)image->m_position.x * multi.x + (float)offset.x, + (float)image->m_position.y * multi.y + (float)offset.y, + (float)(image->m_size.x + image->m_position.x) * multi.x + (float)offset.x, + (float)(image->m_size.y + image->m_position.y) * multi.y + (float)offset.y, + 0xFFFFFFFF, + Display::DRAWIMAGE_ADDITIVE); + } + } else { + captainslog_dbgassert(false, "There is no ControlBarSchemeImage found in the m_layer list"); + } + } + } +} + void ControlBarScheme::Reset() { for (int i = 0; i < LAYER_COUNT; i++) { @@ -49,8 +525,8 @@ void ControlBarScheme::Reset() m_animations.clear(); m_name.Clear(); - m_ScreenCreationRes.x = 0.0f; - m_ScreenCreationRes.y = 0.0f; + m_screenCreationRes.x = 0.0f; + m_screenCreationRes.y = 0.0f; m_side.Clear(); m_buttonQueueImage = nullptr; m_rightHUDImage = nullptr; @@ -128,12 +604,330 @@ void ControlBarScheme::Update_Anim(ControlBarSchemeAnimation *anim) } } +FieldParse ControlBarSchemeManager::m_controlBarSchemeFieldParseTable[] = { + { "ImagePart", &ControlBarSchemeManager::Parse_Image_Part, nullptr, 0 }, + { "AnimatingPart", &ControlBarSchemeManager::Parse_Animating_Part, nullptr, 0 }, + { "ScreenCreationRes", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_screenCreationRes) }, + { "Side", &INI::Parse_AsciiString, nullptr, offsetof(ControlBarScheme, m_side) }, + { "QueueButtonImage", &ImageCollection::Parse_Mapped_Image, nullptr, offsetof(ControlBarScheme, m_buttonQueueImage) }, + { "RightHUDImage", &ImageCollection::Parse_Mapped_Image, nullptr, offsetof(ControlBarScheme, m_rightHUDImage) }, + { "BuildUpClockColor", &INI::Parse_Color_Int, nullptr, offsetof(ControlBarScheme, m_buildUpClockColor) }, + { "ButtonBorderBuildColor", &INI::Parse_Color_Int, nullptr, offsetof(ControlBarScheme, m_borderBuildColor) }, + { "CommandBarBorderColor", &INI::Parse_Color_Int, nullptr, offsetof(ControlBarScheme, m_commandBarBorderColor) }, + { "ButtonBorderActionColor", &INI::Parse_Color_Int, nullptr, offsetof(ControlBarScheme, m_borderActionColor) }, + { "ButtonBorderUpgradeColor", &INI::Parse_Color_Int, nullptr, offsetof(ControlBarScheme, m_borderUpgradeColor) }, + { "ButtonBorderSystemColor", &INI::Parse_Color_Int, nullptr, offsetof(ControlBarScheme, m_borderSystemColor) }, + { "OptionsButtonEnable", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_optionsButtonEnableImage) }, + { "OptionsButtonHightlited", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_optionsButtonHilitedImage) }, + { "OptionsButtonPushed", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_optionsButtonPushedImage) }, + { "OptionsButtonDisabled", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_optionsButtonDisabledImage) }, + { "IdleWorkerButtonEnable", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_idleWorkerButtonEnableImage) }, + { "IdleWorkerButtonHightlited", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_idleWorkerButtonHilitedImage) }, + { "IdleWorkerButtonPushed", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_idleWorkerButtonPushedImage) }, + { "IdleWorkerButtonDisabled", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_idleWorkerButtonDisabledImage) }, + { "BuddyButtonEnable", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_buddyButtonEnableImage) }, + { "BuddyButtonHightlited", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_buddyButtonHilitedImage) }, + { "BuddyButtonPushed", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_buddyButtonPushedImage) }, + { "BuddyButtonDisabled", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_buddyButtonDisabledImage) }, + { "BeaconButtonEnable", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_beaconButtonEnableImage) }, + { "BeaconButtonHightlited", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_beaconButtonHilitedImage) }, + { "BeaconButtonPushed", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_beaconButtonPushedImage) }, + { "BeaconButtonDisabled", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_beaconButtonDisabledImage) }, + { "GenBarButtonIn", &ImageCollection::Parse_Mapped_Image, nullptr, offsetof(ControlBarScheme, m_genBarButtonInImage) }, + { "GenBarButtonOn", &ImageCollection::Parse_Mapped_Image, nullptr, offsetof(ControlBarScheme, m_genBarButtonOnImage) }, + { "ToggleButtonUpIn", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_toggleButtonUpInImage) }, + { "ToggleButtonUpOn", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_toggleButtonUpOnImage) }, + { "ToggleButtonUpPushed", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_toggleButtonUpPushedImage) }, + { "ToggleButtonDownIn", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_toggleButtonDownInImage) }, + { "ToggleButtonDownOn", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_toggleButtonDownOnImage) }, + { "ToggleButtonDownPushed", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_toggleButtonDownPushedImage) }, + { "GeneralButtonEnable", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_generalButtonEnableImage) }, + { "GeneralButtonHightlited", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_generalButtonHilitedImage) }, + { "GeneralButtonPushed", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_generalButtonPushedImage) }, + { "GeneralButtonDisabled", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_generalButtonDisabledImage) }, + { "UAttackButtonEnable", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_uAttackButtonEnableImage) }, + { "UAttackButtonHightlited", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_uAttackButtonHilitedImage) }, + { "UAttackButtonPushed", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_uAttackButtonPushedImage) }, + { "GenArrow", &ImageCollection::Parse_Mapped_Image, nullptr, offsetof(ControlBarScheme, m_genArrowImage) }, + { "MinMaxButtonEnable", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_minMaxButtonEnableImage) }, + { "MinMaxButtonHightlited", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_minMaxButtonHilitedImage) }, + { "MinMaxButtonPushed", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_minMaxButtonPushedImage) }, + { "MinMaxUL", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_minMaxUL) }, + { "MinMaxLR", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_minMaxLR) }, + { "GeneralUL", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_generalUL) }, + { "GeneralLR", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_generalLR) }, + { "UAttackUL", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_uAttackUL) }, + { "UAttackLR", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_uAttackLR) }, + { "OptionsUL", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_optionsUL) }, + { "OptionsLR", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_optionsLR) }, + { "WorkerUL", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_workerUL) }, + { "WorkerLR", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_workerLR) }, + { "ChatUL", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_chatUL) }, + { "ChatLR", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_chatLR) }, + { "BeaconUL", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_beaconUL) }, + { "BeaconLR", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_beaconLR) }, + { "PowerBarUL", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_powerBarUL) }, + { "PowerBarLR", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_powerBarLR) }, + { "MoneyUL", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_moneyUL) }, + { "MoneyLR", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarScheme, m_moneyLR) }, + { "CommandMarkerImage", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_commandMarkerImage) }, + { "ExpBarForegroundImage", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_expBarForegroundImage) }, + { "PowerPurchaseImage", + &ImageCollection::Parse_Mapped_Image, + nullptr, + offsetof(ControlBarScheme, m_powerPurchaseImage) }, + { nullptr, nullptr, nullptr, 0 } +}; + ControlBarSchemeManager::ControlBarSchemeManager() : m_currentScheme(nullptr) { m_multiplyer.x = 1.0f; m_multiplyer.y = 1.0f; } +ControlBarSchemeManager::~ControlBarSchemeManager() +{ + for (auto it = m_schemeList.begin(); it != m_schemeList.end(); it++) { + if (*it != nullptr) { + delete *it; + } + } + + m_schemeList.clear(); + m_currentScheme = nullptr; +} + +void ControlBarSchemeManager::Parse_Image_Part(INI *ini, void *instance, void *store, const void *user_data) +{ + static FieldParse myFieldParse[] = { + { "Position", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarSchemeImage, m_position) }, + { "Size", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarSchemeImage, m_size) }, + { "ImageName", &ImageCollection::Parse_Mapped_Image, nullptr, offsetof(ControlBarSchemeImage, m_image) }, + { "Layer", &INI::Parse_Int, nullptr, offsetof(ControlBarSchemeImage, m_layer) }, + { nullptr, nullptr, nullptr, 0 } + }; + + ControlBarSchemeImage *image = new ControlBarSchemeImage; + ini->Init_From_INI(image, myFieldParse); + static_cast(instance)->Add_Image(image); +} + +void ControlBarSchemeManager::Parse_Animating_Part_Image(INI *ini, void *instance, void *store, const void *user_data) +{ + static FieldParse myFieldParse[] = { + { "Position", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarSchemeImage, m_position) }, + { "Size", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarSchemeImage, m_size) }, + { "ImageName", &ImageCollection::Parse_Mapped_Image, nullptr, offsetof(ControlBarSchemeImage, m_image) }, + { "Layer", &INI::Parse_Int, nullptr, offsetof(ControlBarSchemeImage, m_layer) }, + { nullptr, nullptr, nullptr, 0 } + }; + + ControlBarSchemeImage *image = new ControlBarSchemeImage; + ini->Init_From_INI(image, myFieldParse); + static_cast(instance)->m_animImage = image; +} + +static const LookupListRec s_animTypeNames[] = { { "SLIDE_RIGHT", ControlBarSchemeAnimation::CB_ANIM_SLIDE_RIGHT }, + { nullptr, 0 } }; + +void ControlBarSchemeManager::Parse_Animating_Part(INI *ini, void *instance, void *store, const void *user_data) +{ + static FieldParse myFieldParse[] = { + { "Name", &INI::Parse_AsciiString, nullptr, offsetof(ControlBarSchemeAnimation, m_name) }, + { "Animation", &INI::Parse_Lookup_List, s_animTypeNames, offsetof(ControlBarSchemeAnimation, m_animType) }, + { "Duration", &INI::Parse_Duration_Unsigned_Int, nullptr, offsetof(ControlBarSchemeAnimation, m_animDuration) }, + { "FinalPos", &INI::Parse_ICoord2D, nullptr, offsetof(ControlBarSchemeAnimation, m_finalPos) }, + { "ImagePart", &ControlBarSchemeManager::Parse_Animating_Part_Image, nullptr, 0 }, + { nullptr, nullptr, nullptr, 0 } + }; + + ControlBarSchemeAnimation *anim = new ControlBarSchemeAnimation; + ini->Init_From_INI(anim, myFieldParse); + static_cast(instance)->Add_Animation(anim); + static_cast(instance)->Add_Image(anim->m_animImage); +} + +ControlBarScheme *ControlBarSchemeManager::New_Control_Bar_Scheme(Utf8String name) +{ + ControlBarScheme *scheme = Find_Control_Bar_Scheme(name); + + if (scheme != nullptr) { + captainslog_dbgassert("We're overwriting a previous control bar scheme %s", name.Str()); + scheme->Reset(); + scheme->m_name.Set(name); + scheme->m_name.To_Lower(); + return scheme; + } else { + scheme = new ControlBarScheme(); + + if (scheme != nullptr && !name.Is_Empty()) { + scheme->m_name.Set(name); + scheme->m_name.To_Lower(); + m_schemeList.push_back(scheme); + return scheme; + } else { + captainslog_dbgassert(false, "Could not create controlbar %s", name.Str()); + } + + return nullptr; + } +} + +ControlBarScheme *ControlBarSchemeManager::Find_Control_Bar_Scheme(Utf8String name) +{ + name.To_Lower(); + + for (auto it = m_schemeList.begin(); it != m_schemeList.end(); it++) { + ControlBarScheme *scheme = *it; + + if (scheme == nullptr) { + break; + } + + if (scheme->m_name.Compare_No_Case(name) == 0) { + return scheme; + } + } + + captainslog_debug("There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"); + return nullptr; +} + +void ControlBarSchemeManager::Preload_Assets(TimeOfDayType time_of_day) +{ + for (auto it = m_schemeList.begin(); it != m_schemeList.end(); it++) { + ControlBarScheme *scheme = *it; + + if (scheme != nullptr) { + if (scheme->m_buttonQueueImage != nullptr) { + g_theDisplay->Preload_Texture_Assets(scheme->m_buttonQueueImage->Get_File_Name()); + } + + if (scheme->m_rightHUDImage != nullptr) { + g_theDisplay->Preload_Texture_Assets(scheme->m_rightHUDImage->Get_File_Name()); + } + + for (int i = 0; i < LAYER_COUNT; i++) { + for (auto it2 = scheme->m_layer[i].begin(); it2 != scheme->m_layer[i].end(); it2++) { + ControlBarSchemeImage *scheme_image = *it2; + + if (scheme_image != nullptr) { + Image *image = g_theMappedImageCollection->Find_Image_By_Name(scheme_image->m_name); + + if (image != nullptr) { + g_theDisplay->Preload_Texture_Assets(image->Get_File_Name()); + } + } + } + } + } else { + captainslog_dbgassert(false, "There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"); + } + } +} + void ControlBarSchemeManager::Init() { INI ini; @@ -143,16 +937,21 @@ void ControlBarSchemeManager::Init() "There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList that was just read from the INI file"); } -ControlBarSchemeManager::~ControlBarSchemeManager() +void ControlBarSchemeManager::Set_Control_Bar_Scheme(Utf8String scheme_name) { - for (auto it = m_schemeList.begin(); it != m_schemeList.end(); it++) { - if (*it != nullptr) { - delete *it; - } + ControlBarScheme *scheme = Find_Control_Bar_Scheme(scheme_name); + + if (scheme != nullptr) { + m_multiplyer.x = g_theDisplay->Get_Width() / scheme->m_screenCreationRes.x; + m_multiplyer.y = g_theDisplay->Get_Width() / scheme->m_screenCreationRes.y; + m_currentScheme = scheme; + } else { + captainslog_dbgassert(false, "There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"); } - m_schemeList.clear(); - m_currentScheme = nullptr; + if (m_currentScheme != nullptr) { + m_currentScheme->Init(); + } } void ControlBarSchemeManager::Update() @@ -161,3 +960,122 @@ void ControlBarSchemeManager::Update() m_currentScheme->Update(); } } + +void ControlBarSchemeManager::Draw_Background(ICoord2D offset) +{ + if (m_currentScheme != nullptr) { + m_currentScheme->Draw_Background(m_multiplyer, offset); + } +} + +void ControlBarSchemeManager::Draw_Foreground(ICoord2D offset) +{ + if (m_currentScheme != nullptr) { + m_currentScheme->Draw_Foreground(m_multiplyer, offset); + } +} + +void ControlBarSchemeManager::Set_Control_Bar_Scheme_By_Player_Template(const PlayerTemplate *player_template, bool small) +{ + if (player_template != nullptr) { + Utf8String side = player_template->Get_Side(); + + if (small) { + side.Concat("Small"); + } + + if (m_currentScheme == nullptr || m_currentScheme->m_side.Compare(side) != 0) { + if (side.Is_Empty()) { + side.Set("Observer"); + } + + captainslog_debug("Set_Control_Bar_Scheme_By_Player_Template used %s as its side", side.Str()); + ControlBarScheme *new_scheme = nullptr; + + for (auto it = m_schemeList.begin(); it != m_schemeList.end(); it++) { + ControlBarScheme *scheme = *it; + + if (scheme != nullptr) { + if (scheme->m_side.Compare_No_Case(side) == 0 + && (new_scheme == nullptr || new_scheme->m_screenCreationRes.x < scheme->m_screenCreationRes.x)) { + new_scheme = scheme; + } + } else { + captainslog_dbgassert(false, "There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"); + } + } + + if (new_scheme != nullptr) { + m_multiplyer.x = (float)g_theDisplay->Get_Width() / (float)new_scheme->m_screenCreationRes.x; + m_multiplyer.y = (float)g_theDisplay->Get_Height() / (float)new_scheme->m_screenCreationRes.y; + m_currentScheme = new_scheme; + } else { + m_currentScheme = Find_Control_Bar_Scheme("Default"); + captainslog_debug("There's no ControlBarScheme with a side of %s", side.Str()); + } + + if (m_currentScheme != nullptr) { + m_currentScheme->Init(); + } + } else { + m_currentScheme->Init(); + captainslog_debug("Set_Control_Bar_Scheme_By_Player_Template already is using %s as its side", side.Str()); + } + } +} + +void ControlBarSchemeManager::Set_Control_Bar_Scheme_By_Player(Player *player) +{ + GameWindow *button = g_theWindowManager->Win_Get_Window_From_Id( + nullptr, g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:PopupCommunicator")); + + if (button != nullptr && g_theControlBar != nullptr) { + if (g_theRecorder->Is_Multiplayer()) { + g_theControlBar->Set_Control_Command(button, g_theControlBar->Find_Command_Button("NonCommand_Communicator")); + } else { + g_theControlBar->Set_Control_Command(button, g_theControlBar->Find_Command_Button("NonCommand_BriefingHistory")); + } + } + + if (player != nullptr) { + Utf8String side = player->Get_Side(); + + if (m_currentScheme == nullptr || m_currentScheme->m_side.Compare(side) != 0) { + if (side.Is_Empty()) { + side.Set("Observer"); + } + + captainslog_debug("Set_Control_Bar_Scheme_By_Player used %s as its side", side.Str()); + ControlBarScheme *new_scheme = nullptr; + + for (auto it = m_schemeList.begin(); it != m_schemeList.end(); it++) { + ControlBarScheme *scheme = *it; + + if (scheme != nullptr) { + if (scheme->m_side.Compare_No_Case(side) == 0 + && (new_scheme == nullptr || new_scheme->m_screenCreationRes.x < scheme->m_screenCreationRes.x)) { + new_scheme = scheme; + } + } else { + captainslog_dbgassert(false, "There's no ControlBarScheme in the ControlBarSchemeList:m_schemeList"); + } + } + + if (new_scheme != nullptr) { + m_multiplyer.x = (float)g_theDisplay->Get_Width() / (float)new_scheme->m_screenCreationRes.x; + m_multiplyer.y = (float)g_theDisplay->Get_Height() / (float)new_scheme->m_screenCreationRes.y; + m_currentScheme = new_scheme; + } else { + m_currentScheme = Find_Control_Bar_Scheme("Default"); + captainslog_debug("There's no ControlBarScheme with a side of %s", side.Str()); + } + + if (m_currentScheme != nullptr) { + m_currentScheme->Init(); + } + } else { + m_currentScheme->Init(); + captainslog_debug("Set_Control_Bar_Scheme_By_Player already is using %s as its side", side.Str()); + } + } +} diff --git a/src/game/client/gui/controlbar/controlbarscheme.h b/src/game/client/gui/controlbar/controlbarscheme.h index 370c3ade7..94249f923 100644 --- a/src/game/client/gui/controlbar/controlbarscheme.h +++ b/src/game/client/gui/controlbar/controlbarscheme.h @@ -84,7 +84,7 @@ class ControlBarScheme private: Utf8String m_name; - Coord2D m_ScreenCreationRes; + ICoord2D m_screenCreationRes; Utf8String m_side; Image *m_buttonQueueImage; Image *m_rightHUDImage; @@ -152,6 +152,7 @@ class ControlBarScheme Image *m_powerPurchaseImage; std::list m_layer[LAYER_COUNT]; std::list m_animations; + friend class ControlBarSchemeManager; }; class ControlBarSchemeManager diff --git a/src/game/client/gui/controlbar/controlbarunderconstruction.cpp b/src/game/client/gui/controlbar/controlbarunderconstruction.cpp index e57927604..ecb5fbdf5 100644 --- a/src/game/client/gui/controlbar/controlbarunderconstruction.cpp +++ b/src/game/client/gui/controlbar/controlbarunderconstruction.cpp @@ -40,3 +40,20 @@ void ControlBar::Update_Construction_Text_Display(Object *obj) Gadget_Static_Text_Set_Text(window, text); m_displayedConstructPercent = obj->Get_Construction_Percent(); } + +void ControlBar::Populate_Under_Construction(Object *object_under_construction) +{ + if (object_under_construction != nullptr) { + const CommandButton *button = Find_Command_Button("Command_CancelConstruction"); + GameWindow *window = g_theWindowManager->Win_Get_Window_From_Id( + m_contextParent[5], g_theNameKeyGenerator->Name_To_Key("ControlBar.wnd:ButtonCancelConstruction")); + Set_Control_Command(window, button); + window->Win_Set_Status(WIN_STATUS_USE_OVERLAY_STATES); + Update_Construction_Text_Display(object_under_construction); + ExitInterface *exit = object_under_construction->Get_Object_Exit_Interface(); + + if (exit != nullptr) { + Show_Rally_Point(exit->Get_Rally_Point()); + } + } +} diff --git a/src/game/client/gui/gadget/gadgetpushbutton.cpp b/src/game/client/gui/gadget/gadgetpushbutton.cpp index 17fe2f840..addcd9a12 100644 --- a/src/game/client/gui/gadget/gadgetpushbutton.cpp +++ b/src/game/client/gui/gadget/gadgetpushbutton.cpp @@ -88,3 +88,17 @@ void Gadget_Button_Draw_Overlay_Image(GameWindow *push_button, const Image *imag Call_Function(PICK_ADDRESS(0x005AC470, 0x008F518D), push_button, image); #endif } + +void Gadget_Button_Draw_Inverse_Clock(GameWindow *push_button, int percent, int color) +{ +#ifdef GAME_DLL + Call_Function(PICK_ADDRESS(0x005AC430, 0x008F5140), push_button, percent, color); +#endif +} + +void Gadget_Check_Like_Button_Set_Visual_Check(GameWindow *push_button, bool is_checked) +{ +#ifdef GAME_DLL + Call_Function(PICK_ADDRESS(0x005AC2B0, 0x008F4E41), push_button, is_checked); +#endif +} diff --git a/src/game/common/ini/ini.cpp b/src/game/common/ini/ini.cpp index b632838f6..5a4a34d8b 100644 --- a/src/game/common/ini/ini.cpp +++ b/src/game/common/ini/ini.cpp @@ -88,7 +88,7 @@ const BlockParse TheTypeTable[] = { {"CommandButton", &ControlBar::Parse_Command_Button_Definition}, {"CommandMap", HOOK_BLOCK(0x00498480) /*&INI::parseMetaMapDefinition*/}, {"CommandSet", &ControlBar::Parse_Command_Set_Definition}, - {"ControlBarScheme", HOOK_BLOCK(0x00516BA0) /*&INI::parseControlBarSchemeDefinition*/}, + {"ControlBarScheme", &ControlBar::Parse_Control_Bar_Scheme_Definition}, {"ControlBarResizer", &INI::Parse_Control_Bar_Resizer_Definition}, {"CrateData", HOOK_BLOCK(0x00516B90) /*&INI::parseCrateTemplateDefinition*/}, {"Credits", HOOK_BLOCK(0x00515A20) /*&INI::parseCredits*/}, diff --git a/src/game/logic/object/behavior/behaviormodule.h b/src/game/logic/object/behavior/behaviormodule.h index 227ba7b36..182f6b77d 100644 --- a/src/game/logic/object/behavior/behaviormodule.h +++ b/src/game/logic/object/behavior/behaviormodule.h @@ -29,7 +29,6 @@ class CollideModuleInterface; class ContainModuleInterface; class DamageModuleInterface; class DieModuleInterface; -class DockUpdateInterface; class ExitInterface; class HordeUpdateInterface; class OverchargeBehaviorInterface; @@ -62,6 +61,30 @@ class DestroyModuleInterface virtual void On_Destroy() = 0; }; +class DockUpdateInterface +{ +public: + virtual bool Is_Clear_To_Approach(const Object *docker) const = 0; + virtual bool Reserve_Approach_Position(Object *docker, Coord3D *pos, int *index) = 0; + virtual bool Advance_Approach_Position(Object *docker, Coord3D *pos, int *index) = 0; + virtual bool Is_Clear_To_Enter(const Object *docker) const = 0; + virtual bool Is_Clear_To_Advance(const Object *docker, int index) const = 0; + virtual void Get_Enter_Position(Object *docker, Coord3D *pos) = 0; + virtual void Get_Dock_Position(Object *docker, Coord3D *pos) = 0; + virtual void Get_Exit_Position(Object *docker, Coord3D *pos) = 0; + virtual void On_Approach_Reached(Object *docker) = 0; + virtual void On_Enter_Reached(Object *docker) = 0; + virtual void On_Dock_Reached(Object *docker) = 0; + virtual void On_Exit_Reached(Object *docker) = 0; + virtual bool Action(Object *docker, Object *obj) = 0; + virtual void Cancel_Dock(Object *docker) = 0; + virtual bool Is_Dock_Open() = 0; + virtual void Set_Dock_Open(bool open) = 0; + virtual void Set_Dock_Crippled(bool crippled) = 0; + virtual bool Is_Allow_Passthrough_Type() = 0; + virtual bool Is_Rally_Point_After_Dock_Type() = 0; +}; + class SlavedUpdateInterface { public: @@ -95,13 +118,18 @@ class ProductionEntry : public MemoryPoolObject virtual ~ProductionEntry() override; ProductionID Get_Production_ID() const { return m_productionID; } - const UpgradeTemplate *Get_Production_Object() const { return m_objectToProduce; } - int Get_Type() const { return m_type; } + const UpgradeTemplate *Get_Production_Upgrade() const { return m_upgradeToResearch; } + const ThingTemplate *Get_Production_Object() const { return m_objectToProduce; } + ProductionType Get_Type() const { return m_type; } float Get_Percent_Complete() const { return m_percentComplete; } private: - int m_type; - UpgradeTemplate *m_objectToProduce; + ProductionType m_type; + union + { + ThingTemplate *m_objectToProduce; + UpgradeTemplate *m_upgradeToResearch; + }; ProductionID m_productionID; float m_percentComplete; int m_framesUnderConstruction; diff --git a/src/game/logic/object/update/aiupdate.h b/src/game/logic/object/update/aiupdate.h index 66b62bc17..252cec3b5 100644 --- a/src/game/logic/object/update/aiupdate.h +++ b/src/game/logic/object/update/aiupdate.h @@ -23,7 +23,6 @@ class INI; class DozerAIInterface; class WorkerAIInterface; -class HackInternetAIInterface; class JetAIUpdate; class AIStateMachine; class Path; @@ -31,6 +30,13 @@ class TurretAIData; class TurretAI; class AttackPriorityInfo; +class HackInternetAIInterface +{ +public: + virtual bool Is_Hacking() const = 0; + virtual bool Is_Hacking_Packing_Or_Unpacking() const = 0; +}; + enum AICommandType { AICMD_MOVE_TO_POSITION, diff --git a/src/game/logic/object/update/battleplanupdate.cpp b/src/game/logic/object/update/battleplanupdate.cpp new file mode 100644 index 000000000..45a53eb49 --- /dev/null +++ b/src/game/logic/object/update/battleplanupdate.cpp @@ -0,0 +1,24 @@ +/** + * @file + * + * @author Jonathan Wilson + * + * @brief Battle Plan Update + * + * @copyright Thyme is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version + * 2 of the License, or (at your option) any later version. + * A full copy of the GNU General Public License can be found in + * LICENSE + */ +#include "battleplanupdate.h" + +BattlePlanStatus BattlePlanUpdate::Get_Active_Battle_Plan() +{ + if (m_transitionStatus == TRANSITION_STATUS_IDLE) { + return m_activeBattlePlan; + } else { + return BATTLE_PLAN_STATUS_NONE; + } +} diff --git a/src/game/logic/object/update/battleplanupdate.h b/src/game/logic/object/update/battleplanupdate.h new file mode 100644 index 000000000..9b52db2f6 --- /dev/null +++ b/src/game/logic/object/update/battleplanupdate.h @@ -0,0 +1,82 @@ +/** + * @file + * + * @author Jonathan Wilson + * + * @brief Battle Plan Update + * + * @copyright Thyme is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version + * 2 of the License, or (at your option) any later version. + * A full copy of the GNU General Public License can be found in + * LICENSE + */ +#pragma once +#include "always.h" +#include "player.h" +#include "specialpowerupdatemodule.h" + +enum TransitionStatus +{ + TRANSITION_STATUS_NONE, + TRANSITION_STATUS_UNPACKING, + TRANSITION_STATUS_IDLE, + TRANSITION_STATUS_PACKING, +}; + +class BattlePlanUpdate : public SpecialPowerUpdateModule +{ + IMPLEMENT_POOL(BattlePlanUpdate) +public: + virtual ~BattlePlanUpdate() override; + virtual NameKeyType Get_Module_Name_Key() const override; + virtual void On_Object_Created() override; + virtual void On_Delete() override; + + virtual void CRC_Snapshot(Xfer *xfer) override; + virtual void Xfer_Snapshot(Xfer *xfer) override; + virtual void Load_Post_Process() override; + + virtual SpecialPowerUpdateInterface *Get_Special_Power_Update_Interface() override; + + virtual UpdateSleepTime Update() override; + + virtual void Initiate_Intent_To_Do_Special_Power(const SpecialPowerTemplate *special_power_template, + const Object *target_obj, + const Coord3D *target_pos, + const Waypoint *waypoint, + unsigned int options) override; + virtual bool Is_Special_Ability() const override; + virtual bool Is_Special_Power() const override; + virtual bool Is_Active() const override; + virtual CommandOption Get_Command_Option() const override; + virtual bool Does_Special_Power_Have_Overridable_Destination_Active() const override; + virtual bool Does_Special_Power_Have_Overridable_Destination() const override; + virtual void Set_Special_Power_Overridable_Destination(const Coord3D *destination) override; + virtual bool Is_Power_Currently_In_Use(const CommandButton *button) const override; + + BattlePlanStatus Get_Active_Battle_Plan(); + +private: + BattlePlanStatus m_battlePlanUnk1; + BattlePlanStatus m_battlePlanUnk2; + BattlePlanStatus m_activeBattlePlan; + TransitionStatus m_transitionStatus; + unsigned int m_updateFrame; + SpecialPowerModuleInterface *m_specialPower; + bool m_objectCreated; + bool m_turretOutOfPosition; + BattlePlanBonuses *m_battlePlanBonuses; + AudioEventRTS m_bombardmentPlanUnpackSound; + AudioEventRTS m_bombardmentPlanPackSound; + AudioEventRTS m_bombardmentAnnouncement; + AudioEventRTS m_searchAndDestroyPlanUnpackSound; + AudioEventRTS m_searchAndDestroyPlanIdleLoopSound; + AudioEventRTS m_searchAndDestroyPlanPackSound; + AudioEventRTS m_searchAndDestroyAnnouncement; + AudioEventRTS m_holdTheLinePlanUnpackSound; + AudioEventRTS m_holdTheLinePlanPackSound; + AudioEventRTS m_holdTheLineAnnouncement; + ObjectID m_visionObject; +}; diff --git a/src/hooker/setuphooks_zh.cpp b/src/hooker/setuphooks_zh.cpp index d12bf0634..32efa6630 100644 --- a/src/hooker/setuphooks_zh.cpp +++ b/src/hooker/setuphooks_zh.cpp @@ -3563,4 +3563,39 @@ void Setup_Hooks() Hook_Any(0x005A49F0, ControlBarScheme::Reset); Hook_Any(0x005A6570, ControlBarSchemeManager::Init); Hook_Any(0x005A6620, ControlBarSchemeManager::Update); + + // controlbar.h + // Hook_Any(0x004601C0, ControlBar::Show_Rally_Point); + // Hook_Any(0x00460D70, ControlBar::Switch_Control_Bar_Stage); + // Hook_Any(0x004614F0, ControlBar::Set_Up_Down_Images); + // Hook_Any(0x00460920, ControlBar::Update_Build_Queue_Disabled_Images); + // Hook_Any(0x00460A70, ControlBar::Update_Build_Up_Clock_Color); + // Hook_Any(0x00460A50, ControlBar::Update_Right_HUD_Image); + // Hook_Any(0x00461050, ControlBar::Update_Slot_Exit_Image); + // Hook_Any(0x00461390, ControlBar::Update_Up_Down_Images); + // Hook_Any(0x0045EA80, ControlBar::On_Drawable_Selected); + // Hook_Any(0x0045EAA0, ControlBar::On_Drawable_Deselected); + // Hook_Any(0x0045F8A0, ControlBar::Process_Context_Sensitive_Button_Transition); + // Hook_Any(0x00460900, ControlBar::Preload_Assets); + // Hook_Any(0x00460BB0, ControlBar::Toggle_Control_Bar_Stage); + // Hook_Any(0x00461600, ControlBar::Get_Foreground_Marker_Pos); + // Hook_Any(0x00461640, ControlBar::Trigger_Radar_Attack_Glow); + // Hook_Any(0x005AB0D0, ControlBar::Populate_Beacon); + // Hook_Any(0x005AB250, Beacon_Window_Input); + // Hook_Any(0x005A30D0, ControlBar::Do_Transport_Inventory_UI); + // Hook_Any(0x005A3230, ControlBar::Populate_Command); + // Hook_Any(0x005A3790, ControlBar::Populate_Build_Queue); + // Hook_Any(0x005A3B20, ControlBar::Update_Context_Command); + // Hook_Any(0x005A4090, ControlBar::Get_Command_Availability); + // Hook_Any(0x005AC640, ControlBar::Process_Command_Transition_UI); + // Hook_Any(0x005AB6C0, ControlBar::Add_Common_Commands); + // Hook_Any(0x005AB820, ControlBar::Populate_Multi_Select); + // Hook_Any(0x005AB940, ControlBar::Update_Context_Multi_Select); + // Hook_Any(0x005AAF60, ControlBar::Populate_Under_Construction); + + // controlbarscheme.h + // Hook_Any(0x005A66B0, ControlBarSchemeManager::Draw_Foreground); + // Hook_Any(0x005A66E0, ControlBarSchemeManager::Draw_Background); + Hook_Any(0x005A6710, ControlBarSchemeManager::Set_Control_Bar_Scheme_By_Player_Template); + Hook_Any(0x005A6970, ControlBarSchemeManager::Set_Control_Bar_Scheme_By_Player); }