Several “shield effects” are accomplished by inheriting from BasicShieldWarper
. Much like BasicGraphicEffect
, this actor is not synced to the server.
This actor cannot use the normal method of executing spawn events, so it uses its Spawn
state to do so. If inheriting from this actor and desiring spawn events (such as projectile team colors) to occur, use the SpawnFrame
state instead of a Spawn
state. By overriding the Spawn
state, all of these SFT_PROJCLIENT
spawn functions are skipped, most often meaning no projectile team colors.
The primary thing to consider different from BasicGraphicEffect
is that this actor uses an ACS script to manage when it should disappear. Most instances of this script check for the removal of an inventory item from this actor’s target
called ShieldCheck
, but if you have more specific needs, it may warrant a more complicated script. See below for both a simple example and a more complicated example.
<aside> 🚨 Wait! Stop! Before you copy this actor's definition into your mod, remember the following things:
actor BasicShieldWarper
{
Scale 2.5
Height 0
Radius 0
+NOINTERACTION
+CLIENTSIDEONLY
-SOLID
+NOGRAVITY
+MISSILE
+DONTBLAST
States
{
Spawn:
TNT1 A 0
TNT1 A 0 A_GiveInventory("MM8BDMProjSpawnFuncClient",1)
TNT1 A 0 ACS_NamedExecuteAlways("core_shieldwarper", 0, 0)
TNT1 A 0 A_Jump(256, "Shield")
Goto Shield
Shield:
STAR AABBCCDD 1 A_Warp(AAPTR_TARGET, 0, 0, 16, 0, WARPF_INTERPOLATE|WARPF_NOCHECKPOSITION)
loop
}
}
These are user variables that can be added to the actor for various effects. You do not need to give them a value, they just must be defined.
var int user_NoTranslation
- Disables projectile team colors on this actorvar int user_TranslateWhiteColors
- Allows projectile team colors to recolor white.var int user_TranslateBlackColors
- Allows projectile team colors to recolor black.A basic ShieldWarper
only needs to check for ShieldCheck
. It would need no other functionality beyond what BasicShieldWarper
provides. — Star Crash is one such example.
actor StarCrashWarper : BasicShieldWarper
{
+BRIGHT
States
{
Shield:
STAR AABBCCDD 1 A_Warp(AAPTR_TARGET, 0, 0, 16, 0, WARPF_INTERPOLATE|WARPF_NOCHECKPOSITION)
loop
}
}
However, in more complicated cases, you might need to make your own checks. In this case, you’ll need to put in a bit more effort. An example from vanilla is the 4-shot magazine of Jewel Satellite. Jewel Satellite has 4 warpers that each check for different amounts of JewelShieldCheck
.
actor JewelSatelliteWarper : BasicShieldWarper
{
States
{
Spawn:
TNT1 A 0
TNT1 A 1 A_GiveInventory("MM8BDMProjSpawnFuncClient",1)
TNT1 A 0 ACS_NamedExecuteAlways("core_shieldwarper_jewel", 0, 0) // jewel number is placed into last argument
ShieldLoop:
JEWS AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPP 1 A_Warp(AAPTR_TARGET, 0, 0, 0, 0, WARPF_INTERPOLATE|WARPF_NOCHECKPOSITION)
loop
}
}
actor JewelSatelliteWarper2 : JewelSatelliteWarper
{
States
{
Spawn:
TNT1 A 0
TNT1 A 1 A_GiveInventory("MM8BDMProjSpawnFuncClient",1)
TNT1 A 0 ACS_NamedExecuteAlways("core_shieldwarper_jewel", 0, 1) // second jewel here
Goto ShieldLoop+8
}
}
actor JewelSatelliteWarper3 : JewelSatelliteWarper
{
States
{
Spawn:
TNT1 A 0
TNT1 A 1 A_GiveInventory("MM8BDMProjSpawnFuncClient",1)
TNT1 A 0 ACS_NamedExecuteAlways("core_shieldwarper_jewel", 0, 2) // third
Goto ShieldLoop+16
}
}
actor JewelSatelliteWarper4 : JewelSatelliteWarper
{
States
{
Spawn:
TNT1 A 0
TNT1 A 1 A_GiveInventory("MM8BDMProjSpawnFuncClient",1)
TNT1 A 0 ACS_NamedExecuteAlways("core_shieldwarper_jewel", 0, 3) //etc
Goto ShieldLoop+24
}
}
// Script called by Jewel Satellite
Script "core_shieldwarper_jewel" (int jewelno) CLIENTSIDE
{
int Player = ACS_NamedExecuteWithResult("core_gettarget",0);
int Weapon = ACS_NamedExecuteWithResult("core_getplayerweapon", Player - 1000);
// Loop if shield is active
while(GetActorProperty(Player, APROP_HEALTH)>0
&& ACS_NamedExecuteWithResult("core_getplayerweapon", Player - 1000) == Weapon
&& CheckActorInventory(Player, "ShieldCheck") > 0
&& CheckActorInventory(Player, "JewelShieldCheck") > jewelno
){
Delay(1);
}
// Remove
Thing_Remove(0);
}