Skip to content

PeriodicWeapon#2216

Open
AGAGUGUG wants to merge 2 commits into
Phobos-developers:developfrom
AGAGUGUG:develop
Open

PeriodicWeapon#2216
AGAGUGUG wants to merge 2 commits into
Phobos-developers:developfrom
AGAGUGUG:develop

Conversation

@AGAGUGUG
Copy link
Copy Markdown

The function of this property is to periodically fire weapons at all targets within its range. Currently, it determines which targets are locked by polling the units within its range. Currently, there are the following key-value pairs PeriodicWeapon= PeriodicWeapon.FiringDelay=
PeriodicWeapon.Range=
PeriodicWeapon.AffectsHouses=
PeriodicWeapon.UseInvokerAsOwner=
PeriodicWeapon.FireAll=
PeriodicWeapon.AffectTypes=
PeriodicWeapon.IgnoreTypes=
When the value is 'no', it will only fire at the nearest target within range that can be filtered; when this value is 'yes', it will fire at all targets within range.

@TaranDahl
Copy link
Copy Markdown
Contributor

Docs needed

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 17, 2026

Nightly build for this pull request:

This comment is automatic and is meant to allow guests to get latest nightly builds for this pull request without registering. It is updated on every successful build.

The function of this property is to periodically fire weapons at all targets within its range. Currently, it determines which targets are locked by polling the units within its range. Currently, there are the following key-value pairs PeriodicWeapon=
PeriodicWeapon.FiringDelay=
PeriodicWeapon.Range=
PeriodicWeapon.AffectsHouses=
PeriodicWeapon.UseInvokerAsOwner=
PeriodicWeapon.FireAll=
PeriodicWeapon.AffectTypes=
PeriodicWeapon.IgnoreTypes=
When the value is 'no', it will only fire at the nearest target within range that can be filtered; when this value is 'yes', it will fire at all targets within range.
@phoboscn-bot
Copy link
Copy Markdown

To Chinese users:
This pull request has been mentioned on Phobos CN. There might be relevant details there:

致中文用户:
此拉取请求已在 Phobos CN 上被提及。那里可能有相关详细信息:

https://www.phoboscn.top/t/topic/467/4

Copy link
Copy Markdown
Contributor

@TaranDahl TaranDahl left a comment

Choose a reason for hiding this comment

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

- `ExpireWeapon.UseInvokerAsOwner` can be used to set the house and TechnoType that created the effect (e.g firer of the weapon that applied it) as the weapon's owner & invoker instead of the object the effect is attached to.
- While an attached effect is active, it can periodically fire a weapon at valid targets within range.
- `PeriodicWeapon` sets the `WeaponType` to fire on each interval.
- `PeriodicWeapon.FiringDelay` sets the interval in game frames between firing attempts; must be greater than `0` for periodic firing to run. The timer is initialized to this value when the effect is attached.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

.Delay is enough.
Also, .InitialDelay may be useful.

- `PeriodicWeapon` sets the `WeaponType` to fire on each interval.
- `PeriodicWeapon.FiringDelay` sets the interval in game frames between firing attempts; must be greater than `0` for periodic firing to run. The timer is initialized to this value when the effect is attached.
- `PeriodicWeapon.Range` sets the targeting range in cells from the object the effect is attached to. This value is used for periodic target search instead of the configured weapon's own `Range`; must be greater than `0` for periodic firing to run.
- `PeriodicWeapon.AffectsHouse` controls which owners' units can be targeted, using the same house enumeration as other attached-effect weapon filters (defaults to `all`).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should reuse CanTargetHouses

Comment on lines +47 to +48
- `PeriodicWeapon.AffectTypes`, if set to a non-empty list, restricts targets to the listed `TechnoType`s.
- `PeriodicWeapon.IgnoreTypes`, if set to a non-empty list, excludes the listed `TechnoType`s from targeting.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should be a thing on the weapon side, I think

- `PeriodicWeapon.FireAll`, if set to false (default), fires at only the nearest valid target within range; if set to true, fires at every valid target within range on each interval.
- `PeriodicWeapon.AffectTypes`, if set to a non-empty list, restricts targets to the listed `TechnoType`s.
- `PeriodicWeapon.IgnoreTypes`, if set to a non-empty list, excludes the listed `TechnoType`s from targeting.
- Valid targets must be alive, within range, pass the house and type filters, and not be immune to the weapon's warhead armor modifier (`versus` not `0`). The attached object itself is never targeted. Weapons are fired via simulated firing from the attached object's location.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The attached object itself is never targeted.

May not be good to hard-code that.

- `PeriodicWeapon.Range` sets the targeting range in cells from the object the effect is attached to. This value is used for periodic target search instead of the configured weapon's own `Range`; must be greater than `0` for periodic firing to run.
- `PeriodicWeapon.AffectsHouse` controls which owners' units can be targeted, using the same house enumeration as other attached-effect weapon filters (defaults to `all`).
- `PeriodicWeapon.UseInvokerAsOwner`, if set to true, uses the house and techno that applied the effect as the weapon's owner and firer instead of the object the effect is attached to.
- `PeriodicWeapon.FireAll`, if set to false (default), fires at only the nearest valid target within range; if set to true, fires at every valid target within range on each interval.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think more customizable target selection method is needed.

Comment on lines +7 to +41
bool TechnoExt::IsProjectileEligibleTarget(WeaponTypeClass* const pWeapon, TechnoClass* const pTarget, TechnoClass* const pFirer)
{
if (!pWeapon || !pTarget)
return false;

const auto pBulletType = pWeapon->Projectile;

if (!pBulletType)
return false;

const auto pBulletTypeExt = BulletTypeExt::ExtMap.Find(pBulletType);
const bool inAir = pTarget->IsInAir();

if (inAir)
{
if (!pBulletType->AA)
return false;
}
else
{
if (pFirer && pFirer->GetTechnoType()->LandTargeting != LandTargetingType::Land_Not_OK
&& pBulletType->AA && pBulletTypeExt->AAOnly)
{
return false;
}

if (!pBulletType->AG)
return false;
}

if (pTarget->InWhichLayer() == Layer::Underground && !pBulletTypeExt->AU)
return false;

return true;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should generalize and reuse SplitsProjectileCheck

Comment on lines +642 to +689
if (!pTarget || pTarget == pTechno || pTarget->InLimbo)
continue;

// 1) 距离检查
const int dist = pTarget->DistanceFrom(pTechno);
if (dist > searchRange)
continue;

// 2) AffectsHouse 检查
if (!EnumFunctions::CanTargetHouse(pType->PeriodicWeapon_AffectsHouse, pFirerHouse, pTarget->Owner))
continue;

// 3) AffectTypes / IgnoreTypes 检查
auto const pTargetType = pTarget->GetTechnoType();

if (pType->PeriodicWeapon_AffectTypes.size() > 0)
{
bool found = false;
for (auto const& pAllowed : pType->PeriodicWeapon_AffectTypes)
{
if (pTargetType == pAllowed) { found = true; break; }
}
if (!found) continue;
}

if (pType->PeriodicWeapon_IgnoreTypes.size() > 0)
{
bool ignored = false;
for (auto const& pIgnored : pType->PeriodicWeapon_IgnoreTypes)
{
if (pTargetType == pIgnored) { ignored = true; break; }
}
if (ignored) continue;
}

// 4) 抛射体 AA / AG / AAOnly / AU 索敌检查
if (!TechnoExt::IsProjectileEligibleTarget(pWeapon, pTarget, pFirer))
continue;

// 5) 弹头护甲比率检查
const double versus = GeneralUtils::GetWarheadVersusArmor(pWH, pTarget->GetTechnoType()->Armor);
if (versus == 0.0)
continue;

// 6) 存活检查
if (!pTarget->IsAlive || pTarget->Health <= 0)
continue;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should generalize and reuse IsAllowedSplitsTarget


for (auto const pTarget : validTargets)
{
const int d = pTarget->DistanceFrom(pTechno);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You checked the distance twice. Should do the sorting when you are looking for the target.

if (!pBulletType) continue;

BulletClass* pBullet = pBulletType->CreateBullet(
pTarget, pFirer, pWeapon->Damage, pWeapon->Warhead,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should apply FirepowerMultiplier.

@TaranDahl TaranDahl added ❓New feature Needs improvement ⚙️T2 T2 maintainer review is sufficient labels May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs improvement ❓New feature ⚙️T2 T2 maintainer review is sufficient

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants