Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -763,3 +763,4 @@ This page lists all the individual contributions to the project by their author.
- **RAZER**:
- Wall overlay unit sell exploit fix
- Multiplayer gamespeed fix for RealTimeTimers
- Rebuild last technotype keyboard commands
4 changes: 4 additions & 0 deletions Phobos.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
<ClCompile Include="src\Blowfish\Hooks.Blowfish.cpp" />
<ClCompile Include="src\Ext\Cell\Body.cpp" />
<ClCompile Include="src\Ext\House\Hooks.ForceEnemy.cpp" />
<ClCompile Include="src\Commands\BuildLastOfTab.cpp" />
<ClCompile Include="src\Commands\RebuildTab3Subtypes.cpp" />
<ClCompile Include="src\Commands\ToggleSWSidebar.cpp" />
<ClCompile Include="src\Ext\Sidebar\SWSidebar\SWColumnClass.cpp" />
<ClCompile Include="src\Ext\Sidebar\SWSidebar\SWSidebarClass.cpp" />
Expand Down Expand Up @@ -132,6 +134,7 @@
<ClCompile Include="src\Ext\House\Body.cpp" />
<ClCompile Include="src\Ext\House\Hooks.cpp" />
<ClCompile Include="src\Ext\House\Hooks.AINavalProduction.cpp" />
<ClCompile Include="src\Ext\House\Hooks.BuildLastTab.cpp" />
<ClCompile Include="src\Ext\House\Hooks.UnitFromFactory.cpp" />
<ClCompile Include="src\Ext\ParticleSystemType\Body.cpp" />
<ClCompile Include="src\Ext\RadSite\Body.cpp" />
Expand Down Expand Up @@ -226,6 +229,7 @@
<ClInclude Include="src\Blowfish\blowfish.h" />
<ClInclude Include="src\Ext\Cell\Body.h" />
<ClInclude Include="src\Commands\FireTacticalSW.h" />
<ClInclude Include="src\Commands\RebuildTab3Subtypes.h" />
<ClInclude Include="src\Commands\ToggleSWSidebar.h" />
<ClInclude Include="src\Ext\Sidebar\SWSidebar\SWColumnClass.h" />
<ClInclude Include="src\Ext\Sidebar\SWSidebar\SWSidebarClass.h" />
Expand Down
18 changes: 18 additions & 0 deletions docs/User-Interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,24 @@ For this command to work in multiplayer - you need to use a version of [YRpp spa
- Switches on/off [Task subtitles' label in the middle of the screen](#task-subtitles-display-in-the-middle-of-the-screen).
- For localization add `TXT_TOGGLE_MESSAGE` and `TXT_TOGGLE_MESSAGE_DESC` into your `.csf` file.

### `[ ]` Rebuild Structure
- Re-queue the last produced Power/Resource/Tech Building you placed.

### `[ ]` Rebuild Defense
- Re-queue the last produced Defensive Building you placed.

### `[ ]` Rebuild Infantry
- Re-queue the last produced Infantry Unit you built.

### `[ ]` Rebuild Vehicle
- Re-queue the last produced Vehicle Unit you built.

### `[ ]` Rebuild Aircraft
- Re-queue the last produced Aircraft Unit you built.

### `[ ]` Rebuild Naval
- Re-queue the last produced Naval Unit you built.

## Loading screen

- PCX files can now be used as loadscreen images.
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,7 @@ Fixes / interactions with other extensions:
- Fixed the issue that technos cannot spawn survivors due to non-probabilistic reasons when the tech type was destroyed (by NetsuNegi)
- Fixed the bug that vehicle survivor can spawn on wrong position when transport has been destroyed (by NetsuNegi)
- Fixed the bug that building with `Explodes=yes` use Ares's rubble logic will cause it's owner cannot defeat normally (by NetsuNegi)
- New keyboard commands under `Interface`: `Rebuild Structure`, `Rebuild Defense`, `Rebuild Infantry`, `Rebuild Vehicle`,`Rebuild Aircraft`, `Rebuild Naval` (by RAZER)
```

### 0.4.0.3
Expand Down
99 changes: 99 additions & 0 deletions src/Commands/BuildLastOfTab.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include "BuildLastOfTab.h"

#include <Utilities/GeneralUtils.h>
#include <Ext/House/Body.h>
#include <HouseClass.h>
#include <EventClass.h>
#include <SidebarClass.h>

static constexpr const char* BuildLastTabNames[3] =
{
"RebuildStructure",
"RebuildDefense",
"RebuildInfantry",
};

static constexpr const char* BuildLastTabDescKeys[3] =
{
"RebuildStructure_Desc",
"RebuildDefense_Desc",
"RebuildInfantry_Desc",
};

static constexpr const wchar_t* BuildLastTabUINames[3] =
{
L"Rebuild Structure",
L"Rebuild Defense",
L"Rebuild Infantry",
};

static constexpr const wchar_t* BuildLastTabUIDescs[3] =
{
L"Re-queue the last produced Power/Resources building.",
L"Re-queue the last produced Defense/Combat building.",
L"Re-queue the last produced Infantry unit.",
};

template<int TabIndex>
const char* BuildLastOfTabCommandClass<TabIndex>::GetName() const
{
return BuildLastTabNames[TabIndex];
}

template<int TabIndex>
const wchar_t* BuildLastOfTabCommandClass<TabIndex>::GetUIName() const
{
return GeneralUtils::LoadStringUnlessMissing(BuildLastTabNames[TabIndex], BuildLastTabUINames[TabIndex]);
}

template<int TabIndex>
const wchar_t* BuildLastOfTabCommandClass<TabIndex>::GetUICategory() const
{
return CATEGORY_INTERFACE;
}

template<int TabIndex>
const wchar_t* BuildLastOfTabCommandClass<TabIndex>::GetUIDescription() const
{
static_assert(TabIndex >= 0 && TabIndex < 3, "TabIndex out of range");
return GeneralUtils::LoadStringUnlessMissing(BuildLastTabDescKeys[TabIndex], BuildLastTabUIDescs[TabIndex]);
}

template<int TabIndex>
void BuildLastOfTabCommandClass<TabIndex>::Execute(WWKey eInput) const
{
auto const pPlayer = HouseClass::CurrentPlayer;
if (!pPlayer)
return;

auto const pExt = HouseExt::ExtMap.Find(pPlayer);
if (!pExt)
return;

auto const typeIndex = pExt->LastBuiltPerTab[TabIndex];
if (typeIndex < 0)
return;

// Focus the sidebar to the corresponding tab.
if (SidebarClass::Instance.IsSidebarActive)
{
SidebarClass::Instance.ActiveTabIndex = TabIndex;
SidebarClass::Instance.SidebarNeedsRepaint();
}

auto const rtti = pExt->LastBuiltRTTIPerTab[TabIndex];
auto const isNaval = pExt->LastBuiltIsNavalPerTab[TabIndex];

EventClass::OutList.Add(EventClass(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am pretty sure this bypasses all the legality checks?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will get rejected by the house if the house can't build it. That said, what we did in Vinifera is check if it's present on th sidebar as an icon as a shortcut.

pPlayer->ArrayIndex,
EventType::Produce,
static_cast<int>(rtti),
typeIndex,
isNaval ? TRUE : FALSE
));
}

// Explicit instantiations
template class BuildLastOfTabCommandClass<0>;
template class BuildLastOfTabCommandClass<1>;
template class BuildLastOfTabCommandClass<2>;
16 changes: 16 additions & 0 deletions src/Commands/BuildLastOfTab.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include "Commands.h"

// Re-queue the last produced item from a specific production tab.
// TabIndex: 0 = Power/Infrastructure, 1 = Defense/Combat, 2 = Infantry, 3 = Vehicles/Aircraft
template<int TabIndex>
class BuildLastOfTabCommandClass : public CommandClass
{
public:
virtual const char* GetName() const override;
virtual const wchar_t* GetUIName() const override;
virtual const wchar_t* GetUICategory() const override;
virtual const wchar_t* GetUIDescription() const override;
virtual void Execute(WWKey eInput) const override;
};
8 changes: 8 additions & 0 deletions src/Commands/Commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "ToggleSWSidebar.h"
#include "FireTacticalSW.h"
#include "ToggleMessageList.h"
#include "BuildLastOfTab.h"
#include "RebuildTab3Subtypes.h"

#include <CCINIClass.h>

Expand All @@ -28,6 +30,12 @@ DEFINE_HOOK(0x533066, CommandClassCallback_Register, 0x6)
MakeCommand<ToggleDesignatorRangeCommandClass>();
MakeCommand<ToggleMessageListCommandClass>();
MakeCommand<ToggleSWSidebar>();
MakeCommand<BuildLastOfTabCommandClass<0>>();
MakeCommand<BuildLastOfTabCommandClass<1>>();
MakeCommand<BuildLastOfTabCommandClass<2>>();
MakeCommand<RebuildVehicleCommandClass>();
MakeCommand<RebuildAircraftCommandClass>();
MakeCommand<RebuildNavalCommandClass>();

if (Phobos::Config::SuperWeaponSidebarCommands)
{
Expand Down
137 changes: 137 additions & 0 deletions src/Commands/RebuildTab3Subtypes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#include "RebuildTab3Subtypes.h"

#include <Utilities/GeneralUtils.h>
#include <Ext/House/Body.h>
#include <HouseClass.h>
#include <EventClass.h>
#include <SidebarClass.h>

// Helper: issue a Produce event for a tracked subtype and focus sidebar to tab 3.
static void ExecuteRebuildSubtype(int typeIndex, AbstractType rtti, bool isNaval)
{
auto const pPlayer = HouseClass::CurrentPlayer;
if (!pPlayer)
return;

if (typeIndex < 0)
return;

if (SidebarClass::Instance.IsSidebarActive)
{
SidebarClass::Instance.ActiveTabIndex = 3;
SidebarClass::Instance.SidebarNeedsRepaint();
}

EventClass::OutList.Add(EventClass(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

pPlayer->ArrayIndex,
EventType::Produce,
static_cast<int>(rtti),
typeIndex,
isNaval ? TRUE : FALSE
));
}

// --- RebuildVehicle (non-naval UnitType) ---

const char* RebuildVehicleCommandClass::GetName() const
{
return "RebuildVehicleOnly";
}

const wchar_t* RebuildVehicleCommandClass::GetUIName() const
{
return GeneralUtils::LoadStringUnlessMissing("RebuildVehicleOnly", L"Rebuild Vehicle");
}

const wchar_t* RebuildVehicleCommandClass::GetUICategory() const
{
return CATEGORY_INTERFACE;
}

const wchar_t* RebuildVehicleCommandClass::GetUIDescription() const
{
return GeneralUtils::LoadStringUnlessMissing("RebuildVehicleOnly_Desc", L"Re-queue the last produced ground vehicle (non-naval).");
}

void RebuildVehicleCommandClass::Execute(WWKey eInput) const
{
auto const pPlayer = HouseClass::CurrentPlayer;
if (!pPlayer)
return;

auto const pExt = HouseExt::ExtMap.Find(pPlayer);
if (!pExt)
return;

ExecuteRebuildSubtype(pExt->LastBuiltVehicleTypeIndex, pExt->LastBuiltVehicleRTTI, false);
}

// --- RebuildAircraft (AircraftType) ---

const char* RebuildAircraftCommandClass::GetName() const
{
return "RebuildAircraft";
}

const wchar_t* RebuildAircraftCommandClass::GetUIName() const
{
return GeneralUtils::LoadStringUnlessMissing("RebuildAircraft", L"Rebuild Aircraft");
}

const wchar_t* RebuildAircraftCommandClass::GetUICategory() const
{
return CATEGORY_INTERFACE;
}

const wchar_t* RebuildAircraftCommandClass::GetUIDescription() const
{
return GeneralUtils::LoadStringUnlessMissing("RebuildAircraft_Desc", L"Re-queue the last produced aircraft.");
}

void RebuildAircraftCommandClass::Execute(WWKey eInput) const
{
auto const pPlayer = HouseClass::CurrentPlayer;
if (!pPlayer)
return;

auto const pExt = HouseExt::ExtMap.Find(pPlayer);
if (!pExt)
return;

ExecuteRebuildSubtype(pExt->LastBuiltAircraftTypeIndex, pExt->LastBuiltAircraftRTTI, false);
}

// --- RebuildNaval (naval UnitType) ---

const char* RebuildNavalCommandClass::GetName() const
{
return "RebuildNaval";
}

const wchar_t* RebuildNavalCommandClass::GetUIName() const
{
return GeneralUtils::LoadStringUnlessMissing("RebuildNaval", L"Rebuild Naval");
}

const wchar_t* RebuildNavalCommandClass::GetUICategory() const
{
return CATEGORY_INTERFACE;
}

const wchar_t* RebuildNavalCommandClass::GetUIDescription() const
{
return GeneralUtils::LoadStringUnlessMissing("RebuildNaval_Desc", L"Re-queue the last produced naval unit.");
}

void RebuildNavalCommandClass::Execute(WWKey eInput) const
{
auto const pPlayer = HouseClass::CurrentPlayer;
if (!pPlayer)
return;

auto const pExt = HouseExt::ExtMap.Find(pPlayer);
if (!pExt)
return;

ExecuteRebuildSubtype(pExt->LastBuiltNavalTypeIndex, pExt->LastBuiltNavalRTTI, true);
}
38 changes: 38 additions & 0 deletions src/Commands/RebuildTab3Subtypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once

#include "Commands.h"

// Dedicated rebuild commands for tab 3 subtypes.
// RebuildVehicle: re-queues the last non-naval UnitType.
// RebuildAircraft: re-queues the last AircraftType.
// RebuildNaval: re-queues the last naval UnitType.

class RebuildVehicleCommandClass : public CommandClass
{
public:
virtual const char* GetName() const override;
virtual const wchar_t* GetUIName() const override;
virtual const wchar_t* GetUICategory() const override;
virtual const wchar_t* GetUIDescription() const override;
virtual void Execute(WWKey eInput) const override;
};

class RebuildAircraftCommandClass : public CommandClass
{
public:
virtual const char* GetName() const override;
virtual const wchar_t* GetUIName() const override;
virtual const wchar_t* GetUICategory() const override;
virtual const wchar_t* GetUIDescription() const override;
virtual void Execute(WWKey eInput) const override;
};

class RebuildNavalCommandClass : public CommandClass
{
public:
virtual const char* GetName() const override;
virtual const wchar_t* GetUIName() const override;
virtual const wchar_t* GetUICategory() const override;
virtual const wchar_t* GetUIDescription() const override;
virtual void Execute(WWKey eInput) const override;
};
9 changes: 9 additions & 0 deletions src/Ext/House/Body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,15 @@ void HouseExt::ExtData::Serialize(T& Stm)
.Process(this->RestrictedFactoryPlants)
.Process(this->LastBuiltNavalVehicleType)
.Process(this->ProducingNavalUnitTypeIndex)
.Process(this->LastBuiltPerTab)
.Process(this->LastBuiltRTTIPerTab)
.Process(this->LastBuiltIsNavalPerTab)
.Process(this->LastBuiltVehicleTypeIndex)
.Process(this->LastBuiltAircraftTypeIndex)
.Process(this->LastBuiltNavalTypeIndex)
.Process(this->LastBuiltVehicleRTTI)
.Process(this->LastBuiltAircraftRTTI)
.Process(this->LastBuiltNavalRTTI)
.Process(this->CombatAlertTimer)
.Process(this->NumAirpads_NonMFB)
.Process(this->NumBarracks_NonMFB)
Expand Down
Loading