Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New Feature] Autoload Command Shortcut #1452

Open
wants to merge 90 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
0e604e4
max variety autoload and recursive autoload
psi-cmd Dec 13, 2024
7bc526b
Implement autoload hotkey
psi-cmd Dec 14, 2024
831097e
Implement Autoload Shortcut
psi-cmd Dec 14, 2024
ea03a24
ares tags support
Aephiex Dec 14, 2024
1fba9d4
smarter passenger and vehicle distinction by size
Aephiex Dec 14, 2024
7b5dfad
fix not working
Aephiex Dec 14, 2024
142e751
remove redundant check
Aephiex Dec 14, 2024
bde01c4
comments
Aephiex Dec 14, 2024
caa7a13
mind control support
Aephiex Dec 14, 2024
8f3a38a
mind control support part 2
Aephiex Dec 14, 2024
817147c
prevent CaptureManager null pointer
Aephiex Dec 14, 2024
2e143f0
Merge pull request #1 from Aephiex/autoload
psi-cmd Dec 14, 2024
91f51d2
fix nullptr case not tested
psi-cmd Dec 14, 2024
d57a878
merge with latest develop
psi-cmd Dec 14, 2024
873ff7c
bracket style adjustment
psi-cmd Dec 14, 2024
c17d0b3
Fix transport remaining size calculation
Aephiex Dec 15, 2024
3a6163e
fix comments misleading
Aephiex Dec 15, 2024
01a0c42
Merge pull request #2 from Aephiex/patch-1
psi-cmd Dec 15, 2024
c17f008
code style repair
psi-cmd Dec 15, 2024
6f93c6f
merge fix
psi-cmd Dec 15, 2024
32d0cd7
Add support for bio reactors and tank bunkers
Aephiex Dec 15, 2024
e08b42d
name convention fix after merge
psi-cmd Dec 15, 2024
328ef01
fix no manual enter
Aephiex Dec 15, 2024
ab09055
Update AutoLoad.cpp
Aephiex Dec 15, 2024
0db3a2b
Merge branch 'autoload' into patch-1
Aephiex Dec 15, 2024
219a181
Update AutoLoad.cpp
Aephiex Dec 15, 2024
6cd4cdc
Update Body.h
Aephiex Dec 15, 2024
d9c89a5
Update Body.cpp
Aephiex Dec 15, 2024
3f565c6
Update AutoLoad.cpp
Aephiex Dec 15, 2024
aaff634
by size should be default true
Aephiex Dec 15, 2024
21ec9f3
maybe we should use the "second" as sort of budget value so it is sim…
Aephiex Dec 15, 2024
656121f
oh, one line left
Aephiex Dec 15, 2024
1f121c6
update comment
Aephiex Dec 15, 2024
7a2bd49
larger passengers are loaded first
Aephiex Dec 16, 2024
e495829
Merge pull request #3 from Aephiex/patch-1
psi-cmd Dec 16, 2024
8e40291
solve multiplayer desync
Aephiex Dec 16, 2024
2bc4855
Merge pull request #4 from Aephiex/patch-1
psi-cmd Dec 16, 2024
d062623
Update CREDITS.md
Aephiex Dec 16, 2024
eb1e5e1
Update Whats-New.md
Aephiex Dec 16, 2024
f5dbb3b
Update User-Interface.md
Aephiex Dec 16, 2024
75eb1aa
Merge pull request #5 from Aephiex/patch-1
psi-cmd Dec 16, 2024
b8aed4d
Ignore Force for Clicked Action
psi-cmd Dec 16, 2024
4aa1c0f
get rid of type warning
psi-cmd Dec 16, 2024
bf06f8f
Update User-Interface.md
Aephiex Dec 17, 2024
370fa70
Update Body.cpp
Aephiex Dec 17, 2024
1550d31
Update Body.cpp
Aephiex Dec 17, 2024
836722b
move out from development commands and code clean.
psi-cmd Dec 18, 2024
0f23cca
Merge pull request #6 from Aephiex/patch-1
psi-cmd Dec 18, 2024
f121f60
style fix
psi-cmd Dec 20, 2024
dd403ec
Update CREDITS.md
psi-cmd Dec 20, 2024
36456fd
Update AutoLoad.cpp
Aephiex Dec 21, 2024
8520a5f
Update AutoLoad.cpp
Aephiex Dec 21, 2024
d94a680
Update Body.h
Aephiex Dec 21, 2024
de34130
Update Body.cpp
Aephiex Dec 21, 2024
f3b2029
Update User-Interface.md
Aephiex Dec 21, 2024
5a25372
Update AutoLoad.cpp
Aephiex Dec 21, 2024
2f78fa0
Update AutoLoad.cpp
Aephiex Dec 21, 2024
5b0dd74
Merge pull request #7 from Aephiex/patch-1
psi-cmd Dec 21, 2024
6385f63
Update AutoLoad.cpp
Aephiex Dec 21, 2024
da540d6
Update AutoLoad.cpp
Aephiex Dec 21, 2024
df6ce6e
Merge pull request #8 from Aephiex/patch-1
psi-cmd Dec 23, 2024
0f6c255
fix tank bunker filter
Aephiex Dec 23, 2024
bba2745
pBuilding->Type
Aephiex Dec 23, 2024
6aef490
style and details
Aephiex Dec 24, 2024
117add1
typo
Aephiex Dec 24, 2024
2804cdc
tank bunker check use YR function
Aephiex Dec 24, 2024
e76b691
Update Body.cpp
Aephiex Jan 5, 2025
df2b1ba
Update Body.h
Aephiex Jan 5, 2025
0129076
minor revamp
Aephiex Jan 12, 2025
c369355
fix warning
Aephiex Jan 12, 2025
2bc0ed6
Update Body.cpp
Aephiex Jan 12, 2025
219c3fc
fix budget substraction logic
Aephiex Jan 12, 2025
144f917
Update Body.cpp
Aephiex Jan 12, 2025
96f61ee
Merge branch 'develop' into autoload
Aephiex Jan 16, 2025
ac248c3
auto garrison addition
Aephiex Feb 1, 2025
e5bffac
Update AutoGarrison.cpp
Aephiex Feb 1, 2025
7f97c46
Merge branch 'develop' into autoload
Aephiex Feb 1, 2025
519cec8
auto capture
Aephiex Feb 2, 2025
753b558
Merge branch 'Phobos-developers:develop' into autoload
Aephiex Feb 2, 2025
d15a9ee
fix not working
Aephiex Feb 2, 2025
56ee12f
fix not working
Aephiex Feb 2, 2025
061be2f
prevent crash when trying to interact with buildings outside of the b…
Aephiex Feb 2, 2025
5565c23
prevent interation with fogged buildings
Aephiex Feb 3, 2025
b889417
prevent interation with fogged buildings
Aephiex Feb 3, 2025
6b153cb
minor expansion
Aephiex Feb 3, 2025
6b983a3
minor fixes
Aephiex Feb 3, 2025
a898a64
fixes
Aephiex Feb 3, 2025
90c7d46
Update User-Interface.md
Aephiex Feb 3, 2025
e61f63f
Update User-Interface.md
Aephiex Feb 3, 2025
68ef6bb
prevent interation from objects out of the map
Aephiex Feb 4, 2025
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
7 changes: 6 additions & 1 deletion CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,11 @@ This page lists all the individual contributions to the project by their author.
- Skirmish AI "gather when MCV deploy" behavior dehardcode
- Global value of `RepairBaseNodes`
- **tyuah8** - Drive/Jumpjet/Ship/Teleport locomotor did not power on when it is un-piggybacked bugfix
- **Aephiex** - initial fix for Ares academy not working on the initial payloads of vehicles built from a war factory
- **Aephiex**
- Auto load hotkey command (supplement)
- Auto garrison hotkey command
- Auto capture hotkey command
- initial fix for Ares academy not working on the initial payloads of vehicles built from a war factory
- **Ares developers**
- YRpp and Syringe which are used, save/load, project foundation and generally useful code from Ares
- unfinished RadTypes code
Expand All @@ -412,6 +416,7 @@ This page lists all the individual contributions to the project by their author.
- **Joshy** - Original FlyingStrings implementation
- **CnCVK** - Original custom locomotors experiment
- **ZΞPHYɌUS** - win/lose themes code
- **psi-cmd** - Auto load hotkey command (implementation)
- **Neargye (Daniil Goncharov)** - [nameof library](https://github.com/Neargye/nameof) (MIT)
- **ayylmao** - help with docs, extensive and thorough testing
- **SMxReaver** - help with docs, extensive and thorough testing
Expand Down
6 changes: 6 additions & 0 deletions Phobos.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\Commands\AutoCapture.cpp" />
<ClCompile Include="src\Commands\AutoGarrison.cpp" />
<ClCompile Include="src\Ext\TechnoType\Hooks.MatrixOp.cpp" />
<ClCompile Include="src\New\Entity\AttachEffectClass.cpp" />
<ClCompile Include="src\New\Type\AttachEffectTypeClass.cpp" />
Expand All @@ -31,6 +33,7 @@
<ClCompile Include="src\Commands\ToggleDesignatorRange.cpp" />
<ClCompile Include="src\Commands\ToggleDigitalDisplay.cpp" />
<ClCompile Include="src\Commands\SaveVariablesToFile.cpp" />
<ClCompile Include="src\Commands\AutoLoad.cpp" />
<ClCompile Include="src\Ext\Anim\Body.cpp" />
<ClCompile Include="src\Ext\Anim\Hooks.cpp" />
<ClCompile Include="src\Ext\Anim\Hooks.AnimCreateUnit.cpp" />
Expand Down Expand Up @@ -183,6 +186,8 @@
<ClCompile Include="YRpp\StaticInits.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\Commands\AutoCapture.h" />
<ClInclude Include="src\Commands\AutoGarrison.h" />
<ClInclude Include="src\New\Entity\AttachEffectClass.h" />
<ClInclude Include="src\New\Type\AttachEffectTypeClass.h" />
<ClInclude Include="src\Commands\FrameByFrame.h" />
Expand All @@ -196,6 +201,7 @@
<ClInclude Include="src\Commands\ToggleDesignatorRange.h" />
<ClInclude Include="src\Commands\ToggleDigitalDisplay.h" />
<ClInclude Include="src\Commands\SaveVariablesToFile.h" />
<ClInclude Include="src\Commands\AutoLoad.h" />
<ClInclude Include="src\Ext\Bullet\Trajectories\BombardTrajectory.h" />
<ClInclude Include="src\Ext\Bullet\Trajectories\PhobosTrajectory.h" />
<ClInclude Include="src\Ext\Bullet\Trajectories\StraightTrajectory.h" />
Expand Down
15 changes: 15 additions & 0 deletions docs/Fixed-or-Improved-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,21 @@ Units.RepairPercent= ; floating point value, percents or absolute
Units.UseRepairCost= ; boolean
```

### Limited multi selection of not owned buildings

- It is now possible to multi select (press shift + select) not owned buildings under limited conditions. This is primarily designed to make better use of the [Auto Load](User-Interface.md#--auto-load) command hotkey.
- Garrisonable civilian structures not owned by any house can be made multi-selectable by `[General]->MultiSelectNeutrals.Garrisonable=true`.
- Tech buildings not owned by any house can be made multi-selectable by `[General]->MultiSelectNeutrals.TechBuilding=true`.
- Tech buildings owned by another house can be made multi-selectable by `[General]->MultiSelectNotOwned.TechBuilding=true`.

In `rulesmd.ini`:
```ini
[General]
MultiSelectNeutrals.Garrisonable=false
MultiSelectNeutrals.TechBuilding=false
MultiSelectNotOwned.TechBuilding=false
```

## Particle systems

### Fire particle target coordinate adjustment when firer rotates
Expand Down
33 changes: 33 additions & 0 deletions docs/User-Interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,39 @@ ShowFlashOnSelecting=false ; boolean
- Switches on/off [frame by frame mode](Miscellanous.md#frame-step-in).
- For localization add `TXT_FRAME_BY_FRAME` and `TXT_FRAME_BY_FRAME_DESC` into your `.csf` file.

### `[ ]` Auto Load
- A shortcut to quickly command multiple units to board multiple transports at a same time. Select units and valid transports, then press the hotkey, the units will be distributed among the transports and will be ordered to board them.
- Transports can be considered passengers if fully loaded, or `NoManualEnter=yes`, or it can't actually load anything from the selected passengers.
- Larger passengers are loaded first, and transports with smaller size limits are used first.
- At a given unit size and size limit, passengers will be diversely distributed into transports if possible.
- Ares `Passengers.Allowed=` and `Passengers.Disallowed=` are taken into account.
- It also supports Bio Reactors, Tank Bunkers, and garrisonable structures. Select valid candidates and multiple said buildings while pressing Shift, then press the auto load hotkey, the units will be distributed among these buildings and will be ordered to enter them.
- If auto board transport can happen among selected units, then said logic takes precedence.
- A building is viewed as a Bio Reactor if it has `Passengers` >= 1, and it has `InfantryAbsorb=yes`.
- A building is viewed as a Tank Bunker if it has `Bunker=yes`.
- Neutral buildings can't be selected with own units at a same time. Either make use of [this feature](Fixed-or-Improved-Logics.md#limited-multi-selection-of-not-owned-buildings) to make neutral buildings selectable with own units at a same time, or make use of the Auto Garrison hotkey (see below).
- For localization add `TXT_AUTO_LOAD` and `TXT_AUTO_LOAD_DESC` into your `.csf` file.

### `[ ]` Auto Garrison
- A shortcut to quickly command multiple infantry units to garrison structures at a same time. Select infantry units who are `Occupier=yes`, then press the hotkey, the units will be distributed among the garrisonable structures visible in the player's camera and will be ordered to garrison them.
- Player selected buildings are the top priority and will be targeted nevertheless even if not currently visible in the player's camera. To multi-select owned units and neutral structures at the same time, make use of [this feature](Fixed-or-Improved-Logics.md#limited-multi-selection-of-not-owned-buildings).
- Unlike the Auto Load command, the Auto Garrison command will not stop here.
- Player controlled buildings, namely Battle Bunkers and already garrisoned civilian structures with empty slots, are the 2nd priority and will be targeted if currently visible in the player's camera.
- Neutral structures that are not critically damaged (red HP) will be targeted last.
- For localization add `TXT_AUTO_GARRISON` and `TXT_AUTO_GARRISON_DESC` into your `.csf` file.

### `[ ]` Auto Capture Tech Buildings
- A shortcut to quickly command multiple engineers to capture tech buildings at a same time. Select engineers, then press the hotkey, up to one each engineer will be ordered to capture the tech buildings visible in the player's camera.
- Only tech buildings will be targeted (those with `NeedsEngineer=yes`). To capture enemy base, make ues of the Auto Capture Enemy Base hotkey (see below).
- If `EngineerCaptureLevel` is below 1.0, and `[General]->EngineerAlwaysCaptureTech=false` (*Ares feature*), more than one engineer may be assigned to each tech building.
- Player selected buildings are the top priority and will be targeted nevertheless even if not currently visible in the player's camera. To multi-select owned units and neutral structures at the same time, make use of [this feature](Fixed-or-Improved-Logics.md#limited-multi-selection-of-not-owned-buildings).
- For localization add `TXT_AUTO_CAPTURE_T` and `TXT_AUTO_CAPTURE_T_DESC` into your `.csf` file.

### `[ ]` Auto Capture Enemy Base
- This is a more aggressive variant of the Auto Capture Tech Buildings hotkey command, that the enemy base buildings will be targeted as well.
- If `EngineerCaptureLevel` is below 1.0, more than one engineer may be assigned to each enemy base building.
- For localization add `TXT_AUTO_CAPTURE_B` and `TXT_AUTO_CAPTURE_B_DESC` into your `.csf` file.

## Loading screen

- PCX files can now be used as loadscreen images.
Expand Down
5 changes: 5 additions & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,11 @@ New:
- Allow customizing charge turret delays per burst on a weapon (by Starkku)
- Unit `Speed` setting now accepts floating point values (by Starkku)
- Extending `Power` to all TechnoTypes (by Morton)
- Custom exit cell for infantry factory (by Starkku)
- Auto load hotkey command (by psi-cmd, Aephiex)
- Auto garrison hotkey command (by Aephiex)
- Auto capture hotkey command (by Aephiex)
- Allow limited multi selection of not owned objects to make better use of the auto load hotket (by Aephiex)

Vanilla fixes:
- Allow AI to repair structures built from base nodes/trigger action 125/SW delivery in single player missions (by Trsdy)
Expand Down
165 changes: 165 additions & 0 deletions src/Commands/AutoCapture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#include "AutoCapture.h"
#include "Utilities/GeneralUtils.h"
#include "Ext/Techno/Body.h"
#include <Utilities/Helpers.Alex.h>
#include "AutoLoad.h"
#include <TacticalClass.h>

const char* AutoCaptureCommandClass::GetName() const
{
if (TechBuildingsOnly)
return "AutoCapture.Tech";
else
return "AutoCapture.Base";
}

const wchar_t* AutoCaptureCommandClass::GetUIName() const
{
if (TechBuildingsOnly)
return GeneralUtils::LoadStringUnlessMissing("TXT_AUTO_CAPTURE_T", L"Auto Capture Tech Buildings");
else
return GeneralUtils::LoadStringUnlessMissing("TXT_AUTO_CAPTURE_B", L"Auto Capture Base");
}

const wchar_t* AutoCaptureCommandClass::GetUICategory() const
{
return CATEGORY_CONTROL;
}

const wchar_t* AutoCaptureCommandClass::GetUIDescription() const
{
if (TechBuildingsOnly)
return GeneralUtils::LoadStringUnlessMissing("TXT_AUTO_CAPTURE_T_DESC", L"Auto Capture Tech Buildings");
else
return GeneralUtils::LoadStringUnlessMissing("TXT_AUTO_CAPTURE_B_DESC", L"Auto Capture Base");
}

inline const static bool CanCaptureBuilding(HouseClass* pEngineerOwner, BuildingClass* pBuilding, bool TechBuildingsOnly)
{
if (pBuilding->Type->Capturable
&& (pBuilding->Owner->IsNeutral() || !pBuilding->Owner->IsAlliedWith(pEngineerOwner)))
{
return !TechBuildingsOnly || pBuilding->Type->NeedsEngineer;
}
return false;
}

void AutoCaptureCommandClass::Execute(WWKey eInput) const
{
MapClass::Instance->SetTogglePowerMode(0);
MapClass::Instance->SetWaypointMode(0, false);
MapClass::Instance->SetRepairMode(0);
MapClass::Instance->SetSellMode(0);

std::vector<TechnoClass*> engineerVector;
HouseClass* pEngineerOwner = nullptr;

for (const auto& pUnit : ObjectClass::CurrentObjects())
{
// try to cast to InfantryClass
InfantryClass* pInfantry = abstract_cast<InfantryClass*>(pUnit);

// If not an infantry, or is not under control of the current player, or is in air, then exclude it from the iteration.
if (!pInfantry || pInfantry->Berzerk || !pInfantry->Owner->IsControlledByCurrentPlayer() || pInfantry->IsInAir())
continue;

// If not within usable area then exclude it from the iteration.
if (!MapClass::Instance->IsWithinUsableArea(pInfantry->GetCoords()))
continue;

if (pInfantry->Type->Engineer)
{
if (!pEngineerOwner)
pEngineerOwner = pInfantry->Owner;
if (pInfantry->Owner == pEngineerOwner)
engineerVector.push_back(pInfantry);
}
}

// If no valid engineer selected, we don't do anything in advance.
if (engineerVector.empty())
return;

std::vector<std::pair<TechnoClass*, int>> capturableStructuresSelectedVector;

std::vector<std::pair<TechnoClass*, int>> capturableStructuresVector;

for (const auto& pUnit : ObjectClass::CurrentObjects())
{
// try to cast to BuildingClass
BuildingClass* pBuilding = abstract_cast<BuildingClass*>(pUnit);

// If not an building, or is not under control of the current player, or is in air, then exclude it from the iteration.
if (!pBuilding || pBuilding->Berzerk || pBuilding->IsInAir())
continue;

// If not within usable area then exclude it from the iteration.
if (!MapClass::Instance->IsWithinUsableArea(pBuilding->GetCoords()))
continue;

// - There is currently no need to check if object owner is current player,
// because this hotkey requires at least 2 objects to be selected to do something,
// however the player is normally unable to select 2 objects that are not owned at a same time.
// - Even though we can make use of "MultiSelectNeutrals.Garrisonable" and like,
// this hotkey does nothing anyway if no owned units are selected.

// If it can be captured then add into the top priority list
if (CanCaptureBuilding(pEngineerOwner, pBuilding, TechBuildingsOnly))
{
auto const pBuildingExt = TechnoExt::ExtMap.Find(pBuilding);
auto const budget = pBuildingExt->NeedsMultipleEngineers() ? 10 : 1;
capturableStructuresSelectedVector.push_back(std::make_pair(pBuilding, budget));
}
}

static auto copy_dvc = []<typename T>(const DynamicVectorClass<T>&dvc)
{
std::vector<T> vec(dvc.Count);
std::copy(dvc.begin(), dvc.end(), vec.begin());
return vec;
};

// find capturable structures in the player's camera
for (auto pBuilding : copy_dvc(*BuildingClass::Array))
{
if (!pBuilding || !pBuilding->IsOnMap || !pBuilding->IsAlive || pBuilding->InLimbo || pBuilding->IsSinking)
continue;

// already checked above, no need to do here
if (pBuilding->IsSelected)
continue;

// checks if the building is visible in the player's camera
if (!MapClass::Instance->IsWithinUsableArea(pBuilding->GetCoords())
|| !pBuilding->DiscoveredByCurrentPlayer
|| !TacticalClass::Instance->CoordsToClient(pBuilding->GetCoords()).second)
continue;

if (pBuilding->IsVisible
&& CanCaptureBuilding(pEngineerOwner, pBuilding, TechBuildingsOnly))
{
auto const pBuildingExt = TechnoExt::ExtMap.Find(pBuilding);
auto const budget = pBuildingExt->NeedsMultipleEngineers() ? 10 : 1;
capturableStructuresVector.push_back(std::make_pair(pBuilding, budget));
}
}

if (!capturableStructuresSelectedVector.empty())
{
auto foundTransportSet = AutoLoadCommandClass::SpreadPassengersToTransports(engineerVector, capturableStructuresSelectedVector, Action::Capture, true);
engineerVector.erase(
std::remove_if(engineerVector.begin(), engineerVector.end(),
[foundTransportSet](auto pPassenger)
{
return foundTransportSet.contains(pPassenger);
}),
engineerVector.end());
if (engineerVector.empty())
return;
}

if (!capturableStructuresVector.empty())
{
AutoLoadCommandClass::SpreadPassengersToTransports(engineerVector, capturableStructuresVector, Action::Capture, true);
}
}
16 changes: 16 additions & 0 deletions src/Commands/AutoCapture.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#include "Commands.h"

class AutoCaptureCommandClass : public CommandClass
{
public:
bool TechBuildingsOnly;

// CommandClass
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;
};
Loading