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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ out
# Python bytecode caches
__pycache__/
*.py[cod]

# Personal agent instructions
/AGENTS.md
4 changes: 3 additions & 1 deletion CREDITS.md
Original file line number Diff line number Diff line change
Expand Up @@ -936,4 +936,6 @@ This page lists all the individual contributions to the project by their author.
- Interop export interface for accessing scenario local/global variables
- Add `ClampToScreen` tag for `BannerType` to control whether banner position is clamped to the visible area
- **obsidianus** - Automatic conversion based on health
- **Nuke** - Reload speed adjustment on promotion
- **Nuke**:
- Reload speed adjustment on promotion
- Switch Voxel Turret Depends on MultiWeapon
3 changes: 3 additions & 0 deletions docs/New-or-Enhanced-Logics.md
Original file line number Diff line number Diff line change
Expand Up @@ -2179,6 +2179,9 @@ MindControlSize=1 ; integer
- `MultiWeapon.SelectCount` determines the number of weapons that can be selected by default weapon selection logic. Notice that higher number is bad for performance.
- If the number is smaller than the total amount of weapons, the ones with smaller indices will be picked.
- Other weapons can still be used for logic that specify a weapon index, such as [ForceWeapon](#forcing-specific-weapon-against-certain-targets).
- For VXL vehicles that also set `TurretCount>0`, the turret and barrel VXL models swap based on the currently selected weapon. Weapon index `N` uses `<ImageFile>turN.vxl` / `<ImageFile>barlN.vxl` (weapon 1 -> `<ImageFile>tur.vxl`, weapon 2 -> `<ImageFile>tur1.vxl`, weapon 3 -> `<ImageFile>tur2.vxl`, and so on). No `artmd.ini` changes are needed - just place the extra `.vxl` / `.hva` files into the game directory following the naming convention.
- The number of effective turrets is the smaller of `WeaponCount` and `TurretCount`; a weapon whose index is out of this range falls back to the default turret. Elite weapons follow the same per-index rule. When the unit has no target, the turret stays on the last used weapon instead of reverting to the default.
- Turret and barrel shadows are drawn as usual when `UseTurretShadow=yes`.

In `rulesmd.ini`:
```ini
Expand Down
1 change: 1 addition & 0 deletions docs/Whats-New.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ You can use the migration utility (can be found on [Phobos supplementaries repo]

#### Changes to Phobos behavior

- VXL vehicles can now swap their turret and barrel models per weapon index by using `MultiWeapon` together with `TurretCount`. (by Nuke)
- When the value of the `ProjectileRange` (Ares feature) field on a weapon is greater than 0, weapon range modifiers will be applied. This behavior can be disabled by explicitly setting `ProjectileRange.ApplyModifiers=false` on that weapon; if `ProjectileRange.ApplyModifiers` is not explicitly set, it will fall back to the global default `[CombatDamage] -> ProjectileRange.ApplyModifiers`.
- `Splits.TargetCellRange` < 0 now applies special behaviour where the projectile does not consider nearby cells as additional targets if there are not enough techno targets to match `Cluster` count at all.
- Combat light customizations introduced a bug that removed vanilla behaviour of ignoring detail level / framerate checks for colored combat light. This bug has been fixed but the previous behaviour can be restored by setting `CombatLightDetailLevel.CheckColored` on Warhead or globally under `[AudioVisual]`.
Expand Down
10 changes: 8 additions & 2 deletions docs/locale/zh_CN/LC_MESSAGES/CREDITS.po
Original file line number Diff line number Diff line change
Expand Up @@ -3198,6 +3198,12 @@ msgstr "为 `BannerType` 添加了 `ClampToScreen` 标签以控制横幅位置
msgid "**obsidianus** - Automatic conversion based on health"
msgstr "**obsidianus** - 自动根据血量变形"

msgid "**Nuke** - Reload speed adjustment on promotion"
msgstr "**Nuke** - 升级时调整装填速率"
msgid "**Nuke**:"
msgstr "**Nuke**:"

msgid "Reload speed adjustment on promotion"
msgstr "升级时调整装填速率"

msgid "Switch Voxel Turret Depends on MultiWeapon"
msgstr "根据 MultiWeapon 切换体素炮塔"

26 changes: 26 additions & 0 deletions docs/locale/zh_CN/LC_MESSAGES/New-or-Enhanced-Logics.po
Original file line number Diff line number Diff line change
Expand Up @@ -4815,6 +4815,32 @@ msgstr ""
"其他武器仍可通过 [对特定目标使用特定武器](#forcing-specific-weapon-against-certain-targets) "
"等指定武器索引序号的逻辑来使用。"

msgid ""
"For VXL vehicles that also set `TurretCount>0`, the turret and barrel VXL "
"models swap based on the currently selected weapon. Weapon index `N` uses "
"`<ImageFile>turN.vxl` / `<ImageFile>barlN.vxl` (weapon 1 -> "
"`<ImageFile>tur.vxl`, weapon 2 -> `<ImageFile>tur1.vxl`, weapon 3 -> "
"`<ImageFile>tur2.vxl`, and so on). No `artmd.ini` changes are needed - "
"just place the extra `.vxl` / `.hva` files into the game directory "
"following the naming convention."
msgstr ""
"对于同时设置了 `TurretCount>0` 的 VXL 载具,炮塔和炮管模型会根据当前选中的武器切换。武器索引 `N` 使用 "
"`<ImageFile>turN.vxl` / `<ImageFile>barlN.vxl`(武器 1 -> `<ImageFile>tur.vxl`,武器 2 -> "
"`<ImageFile>tur1.vxl`,武器 3 -> `<ImageFile>tur2.vxl`,以此类推)。无需修改 `artmd.ini` - "
"只需按照命名约定把额外的 `.vxl` / `.hva` 文件放入游戏目录。"

msgid ""
"The number of effective turrets is the smaller of `WeaponCount` and "
"`TurretCount`; a weapon whose index is out of this range falls back to "
"the default turret. Elite weapons follow the same per-index rule. When "
"the unit has no target, the turret stays on the last used weapon instead "
"of reverting to the default."
msgstr ""
"有效炮塔数量取 `WeaponCount` 和 `TurretCount` 中较小的值;武器索引超出该范围的武器回退到默认炮塔。精英武器遵循同样的按索引规则。当单位没有目标时,炮塔保持在上一个使用的武器而不是回退到默认炮塔。"

msgid "Turret and barrel shadows are drawn as usual when `UseTurretShadow=yes`."
msgstr "当 `UseTurretShadow=yes` 时,炮塔和炮管阴影照常绘制。"

msgid "Multi VoiceAttack"
msgstr "多武器的攻击指令音效"

Expand Down
5 changes: 5 additions & 0 deletions docs/locale/zh_CN/LC_MESSAGES/Whats-New.po
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ msgstr ""
msgid "Changes to Phobos behavior"
msgstr "Phobos 行为更改"

msgid ""
"VXL vehicles can now swap their turret and barrel models per weapon index "
"by using `MultiWeapon` together with `TurretCount`."
msgstr "VXL 载具现在可以通过同时使用 `MultiWeapon` 和 `TurretCount`,按武器索引切换炮塔和炮管模型。"

msgid ""
"When the value of the `ProjectileRange` (Ares feature) field on a weapon "
"is greater than 0, weapon range modifiers will be applied. This behavior "
Expand Down
38 changes: 38 additions & 0 deletions src/Ext/Techno/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <Utilities/Helpers.Alex.h>
#include <Utilities/AresHelper.h>
#include <Utilities/AresFunctions.h>
#include <Utilities/Debug.h>
#include <Misc/FlyingStrings.h>

#pragma region GetTechnoType
Expand Down Expand Up @@ -78,6 +79,35 @@ DEFINE_HOOK(0x736480, UnitClass_AI, 0x6)
pThis->CurrentFiringFrame = animCounter;
}

// Make the displayed VXL turret / barrel follow the currently selected
// weapon for MultiWeapon + TurretCount units. When the unit has no target
// (e.g. after issuing an order with a mouse click) the turret stays on the
// last used weapon instead of snapping back to the default turret.
if (pThis->IsAlive && pExt->GetTypeExtData()->IsMultiWeaponTurretEnabled())
{
if (pThis->Target)
{
const int weaponIndex = pThis->SelectWeapon(pThis->Target);
const auto pType = pThis->GetTechnoType();

// Keep the raw weapon index. Weapons beyond the loaded turret count
// (min(WeaponCount, TurretCount)) are handled by the drawing code and
// fall back to the default turret, so they must not be clamped onto the
// last valid turret here.
const int turret = Math::clamp(weaponIndex, 0, Math::max(pType->WeaponCount - 1, 0));

if (pThis->CurrentTurretNumber != turret)
{
Debug::Log("[MultiWeaponTurret] %s SelectWeapon=%d Target=%p -> CurrentTurretNumber=%d (WeaponCount=%d TurretCount=%d).\n",
pType->ID, weaponIndex, static_cast<void*>(pThis->Target), turret, pType->WeaponCount, pType->TurretCount);
}

pThis->CurrentTurretNumber = turret;
}
// No target: keep the last used weapon's turret (CurrentTurretNumber is
// left untouched so the displayed turret does not jump around).
}

return 0;
}

Expand Down Expand Up @@ -228,6 +258,14 @@ DEFINE_HOOK(0x6FA540, TechnoClass_AI_ChargeTurret, 0x6)

GET(TechnoClass*, pThis, ESI);

// Do not let the charge turret logic touch CurrentTurretNumber for units
// that use the MultiWeapon turret switching feature.
if (auto const pUnitType = abstract_cast<UnitTypeClass*>(pThis->GetTechnoType()))
{
if (UnitTypeExt::Fetch(pUnitType)->IsMultiWeaponTurretEnabled())
return SkipGameCode;
}

if (pThis->ChargeTurretDelay <= 0)
{
pThis->CurrentTurretNumber = 0;
Expand Down
Loading
Loading