PeriodicWeapon#2216
Conversation
|
Docs needed |
|
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.
|
To Chinese users:
|
| - `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. |
There was a problem hiding this comment.
.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`). |
There was a problem hiding this comment.
Should reuse CanTargetHouses
| - `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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
I think more customizable target selection method is needed.
| 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; | ||
| } |
There was a problem hiding this comment.
Should generalize and reuse SplitsProjectileCheck
| 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; | ||
|
|
There was a problem hiding this comment.
Should generalize and reuse IsAllowedSplitsTarget
|
|
||
| for (auto const pTarget : validTargets) | ||
| { | ||
| const int d = pTarget->DistanceFrom(pTechno); |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
Should apply FirepowerMultiplier.
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.