Added original Sentry as a separate item, and made it spawn in Backpacks, while the bigger Sentry is a rare Berserk replacement.
PNG optimization.
This commit is contained in:
parent
d7fe8cbfdd
commit
07121636f5
14 changed files with 499 additions and 18 deletions
15
ItemLore.md
15
ItemLore.md
|
|
@ -181,10 +181,21 @@ infinitely regenerating supply of both, but only one can be used at a time.
|
||||||
These merely existed as a gimmick to show off dynamic lighting in Unreal
|
These merely existed as a gimmick to show off dynamic lighting in Unreal
|
||||||
Engine, so they're not very practical or balanced.
|
Engine, so they're not very practical or balanced.
|
||||||
|
|
||||||
|
## Light Sentry
|
||||||
|
|
||||||
|
Pocket turrets that shoot at any enemies standing in front of them. Easy to
|
||||||
|
carry and deploy, but once they're out in the field that's it. They will keep
|
||||||
|
going until they run out of ammo or battery, after which they will
|
||||||
|
self-destruct.
|
||||||
|
|
||||||
## Minigun Sentry
|
## Minigun Sentry
|
||||||
|
|
||||||
A deployable little helper that will gun down any enemies that stand in its
|
A big, heavy turret that will gun down any enemies that stand in its view
|
||||||
view range. Starts with a full 200 bullets, and must be replenished by players.
|
range.
|
||||||
|
|
||||||
|
Unlike the Light Sentries this one has a much wider range of view and can be
|
||||||
|
resupplied with extra ammo. Conveniently, you can also recall it to put it back
|
||||||
|
in your inventory. While carried it will slowly repair any damage it has taken.
|
||||||
|
|
||||||
In deathmatch, the Sentry will "switch owners" to whoever last replenished it
|
In deathmatch, the Sentry will "switch owners" to whoever last replenished it
|
||||||
with ammunition, like the Turrets in ChaosUT.
|
with ammunition, like the Turrets in ChaosUT.
|
||||||
|
|
|
||||||
|
|
@ -102,8 +102,8 @@
|
||||||
redone the whole thing. Since I didn't feel like making new textures this
|
redone the whole thing. Since I didn't feel like making new textures this
|
||||||
thing now mixes and matches a couple weapon skins.
|
thing now mixes and matches a couple weapon skins.
|
||||||
- It's composed of two models so the gun part can rotate independently.
|
- It's composed of two models so the gun part can rotate independently.
|
||||||
- Thinking of making an alternate item that still uses the source model and
|
- Original version is available as a separate item. Gave it some stitched
|
||||||
its frankenUVs. Will have to stitch a skin for it tho.
|
textures.
|
||||||
|
|
||||||
### Peacemaker
|
### Peacemaker
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,8 @@ Doom Tournament (currently the devel branch is required).
|
||||||
- SCUBA Gear (replaces radsuit if map has swimmable water)
|
- SCUBA Gear (replaces radsuit if map has swimmable water)
|
||||||
- Motion Detector (replaces computer map)
|
- Motion Detector (replaces computer map)
|
||||||
- Light & Dark Flares
|
- Light & Dark Flares
|
||||||
- Minigun Sentry (rare spawn in backpacks)
|
- Minigun Sentry (rare berserk replacement)
|
||||||
|
- Light Sentry (rare spawn in backpacks)
|
||||||
|
|
||||||
## In progress
|
## In progress
|
||||||
|
|
||||||
|
|
@ -79,8 +80,6 @@ Doom Tournament (currently the devel branch is required).
|
||||||
- Demolisher (slot 9) (replaces bfg9000)
|
- Demolisher (slot 9) (replaces bfg9000)
|
||||||
- Autocannon (slot 0) (replaces bfg9000)
|
- Autocannon (slot 0) (replaces bfg9000)
|
||||||
|
|
||||||
- Original Sentry Gun (rare spawn in backpacks)
|
|
||||||
|
|
||||||
## Known bugs
|
## Known bugs
|
||||||
|
|
||||||
- N/A
|
- N/A
|
||||||
|
|
|
||||||
19
gldefs.txt
19
gldefs.txt
|
|
@ -350,6 +350,21 @@ Object MinigunSentry
|
||||||
Frame "SENFQ" { light "SENTRYLIGHT2" }
|
Frame "SENFQ" { light "SENTRYLIGHT2" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlickerLight2 SENTRYLIGHT3
|
||||||
|
{
|
||||||
|
Color 1.0 0.6 0.0
|
||||||
|
Size 40
|
||||||
|
SecondarySize 48
|
||||||
|
Interval 0.1
|
||||||
|
Offset 0 16 10
|
||||||
|
}
|
||||||
|
|
||||||
|
Object SentryGun
|
||||||
|
{
|
||||||
|
Frame "SENFA" { light "SENTRYLIGHT3" }
|
||||||
|
Frame "SENFC" { light "SENTRYLIGHT3" }
|
||||||
|
}
|
||||||
|
|
||||||
// Shaders / Brightmaps
|
// Shaders / Brightmaps
|
||||||
HardwareShader Texture "graphics/MenuBarr.png"
|
HardwareShader Texture "graphics/MenuBarr.png"
|
||||||
{
|
{
|
||||||
|
|
@ -733,3 +748,7 @@ HardwareShader Texture "models/OLSMP_.png"
|
||||||
Texture "masktex" "models/OLSMP_m.png"
|
Texture "masktex" "models/OLSMP_m.png"
|
||||||
texture "envtex" "models/OLSMP_env.png"
|
texture "envtex" "models/OLSMP_env.png"
|
||||||
}
|
}
|
||||||
|
HardwareShader Texture "models/JSentry1_.png"
|
||||||
|
{
|
||||||
|
Shader "shaders/glsl/AmbientGlow.fp"
|
||||||
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
graphics/icons/I_OSntry.png
Normal file
BIN
graphics/icons/I_OSntry.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
24
language.txt
24
language.txt
|
|
@ -33,7 +33,9 @@ O_FLAMETHROWER = "%o was thoroughly roasted by %k's Flamethrower.";
|
||||||
O_BIGGUN = "%k blew a hole through %o with the Demolisher.";
|
O_BIGGUN = "%k blew a hole through %o with the Demolisher.";
|
||||||
O_SMINI = "%o got blasted into steaming chunks by %k's Autocannon.";
|
O_SMINI = "%o got blasted into steaming chunks by %k's Autocannon.";
|
||||||
O_SENTRY = "%%o shouldn't have walked into the sights of %s.";
|
O_SENTRY = "%%o shouldn't have walked into the sights of %s.";
|
||||||
O_OWNSENTRY = "%o was gunned down by %p own Sentry.";
|
O_OWNSENTRY = "%o was gunned down by %p own Minigun Sentry.";
|
||||||
|
O_OSENTRY = "%%o took a bullet from %s.";
|
||||||
|
O_OWNOSENTRY = "%o took a bullet from %p own Light Sentry.";
|
||||||
O_STINGERX = "%o ate flaming Tarydium death thanks to %k.";
|
O_STINGERX = "%o ate flaming Tarydium death thanks to %k.";
|
||||||
O_OLSMP = "%o didn't stand a chance against %k's SMP 7243.";
|
O_OLSMP = "%o didn't stand a chance against %k's SMP 7243.";
|
||||||
/* Pickup messages */
|
/* Pickup messages */
|
||||||
|
|
@ -76,7 +78,8 @@ I_FLAMEGUN = "You got the Fireblaster.";
|
||||||
I_FLAMETHROWER = "You got the Flamethrower.";
|
I_FLAMETHROWER = "You got the Flamethrower.";
|
||||||
I_BIGGUN = "You picked up the Demolisher.";
|
I_BIGGUN = "You picked up the Demolisher.";
|
||||||
I_SMINI = "You got the Autocannon.";
|
I_SMINI = "You got the Autocannon.";
|
||||||
I_SENTRY = "You picked up a Sentry.";
|
I_SENTRY = "You picked up a Minigun Sentry.";
|
||||||
|
I_OSENTRY = "You picked up a Light Sentry.";
|
||||||
I_TRANSLATOR = "You picked up the Universal Translator.";
|
I_TRANSLATOR = "You picked up the Universal Translator.";
|
||||||
I_UARMOR = "You got the Assault Vest.";
|
I_UARMOR = "You got the Assault Vest.";
|
||||||
I_KEVSUIT = "You picked up the Kevlar Suit.";
|
I_KEVSUIT = "You picked up the Kevlar Suit.";
|
||||||
|
|
@ -138,8 +141,10 @@ T_FLAMEGUN = "Fireblaster";
|
||||||
T_FLAMETHROWER = "Flamethrower";
|
T_FLAMETHROWER = "Flamethrower";
|
||||||
T_BIGGUN = "Demolisher";
|
T_BIGGUN = "Demolisher";
|
||||||
T_SMINI = "Autocannon";
|
T_SMINI = "Autocannon";
|
||||||
T_SENTRY = "Sentry";
|
T_SENTRY = "Minigun Sentry";
|
||||||
T_OWNEDSENTRY = "%s's Sentry";
|
T_OSENTRY = "Light Sentry";
|
||||||
|
T_OWNEDSENTRY = "%s's Minigun Sentry";
|
||||||
|
T_OWNEDOSENTRY = "%s's Light Sentry";
|
||||||
T_TRANSLATOR = "Translator";
|
T_TRANSLATOR = "Translator";
|
||||||
T_UARMOR = "Assault Vest";
|
T_UARMOR = "Assault Vest";
|
||||||
T_KEVSUIT = "Kevlar Suit";
|
T_KEVSUIT = "Kevlar Suit";
|
||||||
|
|
@ -186,9 +191,9 @@ D_FLASHLIGHT = "The Flashlight batteries have died.";
|
||||||
D_SEARCHLIGHT = "The Searchlight has run out of battery.";
|
D_SEARCHLIGHT = "The Searchlight has run out of battery.";
|
||||||
D_DETECTOR = "The Detector has run out of battery.";
|
D_DETECTOR = "The Detector has run out of battery.";
|
||||||
D_LBOOTS = "The Jump Boots have drained.";
|
D_LBOOTS = "The Jump Boots have drained.";
|
||||||
M_SENTRYDOWN = "Your Sentry has been destroyed.";
|
M_SENTRYDOWN = "Your Minigun Sentry has been destroyed.";
|
||||||
M_SENTRYDRY = "Your Sentry has run out of ammo.";
|
M_SENTRYDRY = "Your Minigun Sentry has run out of ammo.";
|
||||||
M_SENTRYHIJACK = "Your Sentry has been hijacked.";
|
M_SENTRYHIJACK = "Your Minigun Sentry has been hijacked.";
|
||||||
M_MSNOROOM = "No room to deploy Sentry.";
|
M_MSNOROOM = "No room to deploy Sentry.";
|
||||||
M_NSTOOFAR = "Cannot recall Sentry from this distance.";
|
M_NSTOOFAR = "Cannot recall Sentry from this distance.";
|
||||||
M_FFNOROOM = "No room to activate Force Field.";
|
M_FFNOROOM = "No room to activate Force Field.";
|
||||||
|
|
@ -268,6 +273,8 @@ O_BIGGUN = "%k abrió un hoyo a través de %o con el Demoledor.";
|
||||||
O_SMINI = "%o fue reventad@[ao_esp] en pedazos humeantes por el Autocañón de %k.";
|
O_SMINI = "%o fue reventad@[ao_esp] en pedazos humeantes por el Autocañón de %k.";
|
||||||
O_SENTRY = "%%o no debería haberse metido en el punto de mira de la %s.";
|
O_SENTRY = "%%o no debería haberse metido en el punto de mira de la %s.";
|
||||||
O_OWNSENTRY = "%o fue abatid@[ao_esp] por su propi@[ao_esp] Torreta.";
|
O_OWNSENTRY = "%o fue abatid@[ao_esp] por su propi@[ao_esp] Torreta.";
|
||||||
|
O_OSENTRY = "%%o se llevó un tiro de la %s.";
|
||||||
|
O_OWNOSENTRY = "%o se llevó un tiro de su propi@[ao_esp] Torreta Ligera.";
|
||||||
O_STINGERX = "%o tragó muerte ardiente de Tarydium gracias a %k.";
|
O_STINGERX = "%o tragó muerte ardiente de Tarydium gracias a %k.";
|
||||||
O_OLSMP = "%o no tenía ninguna oportunidad contra el SMP 7243 de %k.";
|
O_OLSMP = "%o no tenía ninguna oportunidad contra el SMP 7243 de %k.";
|
||||||
/* Pickup messages */
|
/* Pickup messages */
|
||||||
|
|
@ -311,6 +318,7 @@ I_FLAMETHROWER = "Has obtenido el Lanzallamas.";
|
||||||
I_BIGGUN = "Has recogido el Demoledor.";
|
I_BIGGUN = "Has recogido el Demoledor.";
|
||||||
I_SMINI = "Has obtenido el Autocañón.";
|
I_SMINI = "Has obtenido el Autocañón.";
|
||||||
I_SENTRY = "Has recogido una Torreta.";
|
I_SENTRY = "Has recogido una Torreta.";
|
||||||
|
I_OSENTRY = "Has recogido una Torreta Ligera.";
|
||||||
I_TRANSLATOR = "Has obtenido el Traductor Universal.";
|
I_TRANSLATOR = "Has obtenido el Traductor Universal.";
|
||||||
I_UARMOR = "Has obtenido la Coraza de Asalto.";
|
I_UARMOR = "Has obtenido la Coraza de Asalto.";
|
||||||
I_KEVSUIT = "Has recogido el Traje de Kevlar.";
|
I_KEVSUIT = "Has recogido el Traje de Kevlar.";
|
||||||
|
|
@ -370,6 +378,8 @@ T_BIGGUN = "Demoledor";
|
||||||
T_SMINI = "Autocañón";
|
T_SMINI = "Autocañón";
|
||||||
T_SENTRY = "Torreta";
|
T_SENTRY = "Torreta";
|
||||||
T_OWNEDSENTRY = "Torreta de %s";
|
T_OWNEDSENTRY = "Torreta de %s";
|
||||||
|
T_OSENTRY = "Torreta Ligera";
|
||||||
|
T_OWNEDOSENTRY = "Torreta Ligera de %s";
|
||||||
T_TRANSLATOR = "Traductor";
|
T_TRANSLATOR = "Traductor";
|
||||||
T_UARMOR = "Coraza de Asalto";
|
T_UARMOR = "Coraza de Asalto";
|
||||||
T_KEVSUIT = "Traje de Kevlar";
|
T_KEVSUIT = "Traje de Kevlar";
|
||||||
|
|
|
||||||
|
|
@ -673,6 +673,97 @@ Model "MinigunSentryBase"
|
||||||
FrameIndex SENU R 0 67
|
FrameIndex SENU R 0 67
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Model "SentryGunItem"
|
||||||
|
{
|
||||||
|
Path "models"
|
||||||
|
Model 0 "SentryM_d.3d"
|
||||||
|
SurfaceSkin 0 1 "JSentry1_.png"
|
||||||
|
AngleOffset -90
|
||||||
|
Scale 0.12 0.12 0.144
|
||||||
|
ZOffset 16
|
||||||
|
|
||||||
|
FrameIndex SENT A 0 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Model "SentryGunX"
|
||||||
|
{
|
||||||
|
Path "models"
|
||||||
|
Model 0 "SentryM_d.3d"
|
||||||
|
SurfaceSkin 0 0 "JSentry1.png"
|
||||||
|
AngleOffset -90
|
||||||
|
Scale 0.12 0.12 0.144
|
||||||
|
ZOffset 16
|
||||||
|
DONTCULLBACKFACES
|
||||||
|
|
||||||
|
FrameIndex SENF A 0 20
|
||||||
|
FrameIndex SENF C 0 22
|
||||||
|
}
|
||||||
|
|
||||||
|
Model "SentryGun"
|
||||||
|
{
|
||||||
|
Path "models"
|
||||||
|
Model 0 "SentryM_d.3d"
|
||||||
|
SurfaceSkin 0 1 "JSentry1.png"
|
||||||
|
AngleOffset -90
|
||||||
|
Scale 0.12 0.12 0.144
|
||||||
|
ZOffset 16
|
||||||
|
|
||||||
|
// Spawn
|
||||||
|
FrameIndex SENT A 0 0
|
||||||
|
// Up
|
||||||
|
FrameIndex SENR A 0 0
|
||||||
|
FrameIndex SENR B 0 1
|
||||||
|
FrameIndex SENR C 0 2
|
||||||
|
FrameIndex SENR D 0 3
|
||||||
|
FrameIndex SENR E 0 4
|
||||||
|
// Still
|
||||||
|
FrameIndex SENI A 0 5
|
||||||
|
// Wind
|
||||||
|
FrameIndex SENW A 0 6
|
||||||
|
FrameIndex SENW B 0 7
|
||||||
|
FrameIndex SENW C 0 8
|
||||||
|
FrameIndex SENW D 0 9
|
||||||
|
FrameIndex SENW E 0 10
|
||||||
|
FrameIndex SENW F 0 11
|
||||||
|
FrameIndex SENW G 0 12
|
||||||
|
FrameIndex SENW H 0 13
|
||||||
|
FrameIndex SENW I 0 14
|
||||||
|
FrameIndex SENW J 0 15
|
||||||
|
FrameIndex SENW K 0 16
|
||||||
|
FrameIndex SENW L 0 17
|
||||||
|
FrameIndex SENW M 0 18
|
||||||
|
FrameIndex SENW N 0 19
|
||||||
|
// Fire
|
||||||
|
FrameIndex SENF A 0 20
|
||||||
|
FrameIndex SENF B 0 21
|
||||||
|
FrameIndex SENF C 0 22
|
||||||
|
FrameIndex SENF D 0 23
|
||||||
|
// Unwind
|
||||||
|
FrameIndex SENU A 0 24
|
||||||
|
FrameIndex SENU B 0 25
|
||||||
|
FrameIndex SENU C 0 26
|
||||||
|
FrameIndex SENU D 0 27
|
||||||
|
FrameIndex SENU E 0 28
|
||||||
|
FrameIndex SENU F 0 29
|
||||||
|
FrameIndex SENU G 0 30
|
||||||
|
FrameIndex SENU H 0 31
|
||||||
|
FrameIndex SENU I 0 32
|
||||||
|
FrameIndex SENU J 0 33
|
||||||
|
FrameIndex SENU K 0 34
|
||||||
|
FrameIndex SENU L 0 35
|
||||||
|
FrameIndex SENU M 0 36
|
||||||
|
FrameIndex SENU N 0 37
|
||||||
|
FrameIndex SENU O 0 38
|
||||||
|
FrameIndex SENU P 0 39
|
||||||
|
FrameIndex SENU Q 0 40
|
||||||
|
// Down
|
||||||
|
FrameIndex SEND A 0 41
|
||||||
|
FrameIndex SEND B 0 42
|
||||||
|
FrameIndex SEND C 0 43
|
||||||
|
FrameIndex SEND D 0 44
|
||||||
|
FrameIndex SEND E 0 45
|
||||||
|
}
|
||||||
|
|
||||||
Model "MotionDetector"
|
Model "MotionDetector"
|
||||||
{
|
{
|
||||||
Path "models"
|
Path "models"
|
||||||
|
|
|
||||||
BIN
models/JSentry1.png
Normal file
BIN
models/JSentry1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
BIN
models/JSentry1_.png
Normal file
BIN
models/JSentry1_.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
BIN
models/SentryM_a.3d
Normal file
BIN
models/SentryM_a.3d
Normal file
Binary file not shown.
BIN
models/SentryM_d.3d
Normal file
BIN
models/SentryM_d.3d
Normal file
Binary file not shown.
|
|
@ -88,7 +88,7 @@ Class UnrealBackpack : BackpackItem replaces Backpack
|
||||||
Super.DoPickupSpecial(toucher);
|
Super.DoPickupSpecial(toucher);
|
||||||
if ( gameinfo.gametype&GAME_DOOMCHEX )
|
if ( gameinfo.gametype&GAME_DOOMCHEX )
|
||||||
{
|
{
|
||||||
static const Class<Inventory> xitems[] = {"Flare", "Seeds", "SentryItem", "VoiceBox", "ForceField", "Dampener", "Peacemaker"};
|
static const Class<Inventory> xitems[] = {"Flare", "Seeds", "SentryGunItem", "VoiceBox", "ForceField", "Dampener", "Peacemaker"};
|
||||||
int xitemn[7];
|
int xitemn[7];
|
||||||
xitemn[0] = max(0,Random[BackpackExtra](-1,3));
|
xitemn[0] = max(0,Random[BackpackExtra](-1,3));
|
||||||
xitemn[1] = max(0,Random[BackpackExtra](-1,3));
|
xitemn[1] = max(0,Random[BackpackExtra](-1,3));
|
||||||
|
|
@ -1432,6 +1432,11 @@ Class SentryItem : UnrealInventory
|
||||||
UnrealInventory.Charge MinigunSentryBase.sentryhealth;
|
UnrealInventory.Charge MinigunSentryBase.sentryhealth;
|
||||||
+UNREALINVENTORY.DRAWSPECIAL;
|
+UNREALINVENTORY.DRAWSPECIAL;
|
||||||
}
|
}
|
||||||
|
override bool HandlePickup( Inventory item )
|
||||||
|
{
|
||||||
|
if ( item.GetClass() == GetClass() ) return true; // can never get more than one
|
||||||
|
return Super.HandlePickup(item);
|
||||||
|
}
|
||||||
static void TransferOwnership( Actor newowner, Actor sentry )
|
static void TransferOwnership( Actor newowner, Actor sentry )
|
||||||
{
|
{
|
||||||
if ( sentry.master ) sentry.master.TakeInventory("SentryItem",200);
|
if ( sentry.master ) sentry.master.TakeInventory("SentryItem",200);
|
||||||
|
|
@ -1500,7 +1505,11 @@ Class SentryItem : UnrealInventory
|
||||||
override void DoEffect()
|
override void DoEffect()
|
||||||
{
|
{
|
||||||
Super.DoEffect();
|
Super.DoEffect();
|
||||||
if ( !bActive ) return;
|
if ( !bActive )
|
||||||
|
{
|
||||||
|
if ( !(level.maptime%10) ) Charge = min(DefaultCharge,Charge+1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ( !tracer )
|
if ( !tracer )
|
||||||
{
|
{
|
||||||
bActive = false;
|
bActive = false;
|
||||||
|
|
@ -2015,7 +2024,11 @@ Class MinigunSentryBase : Actor
|
||||||
Vector3 x, y, z;
|
Vector3 x, y, z;
|
||||||
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
|
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
|
||||||
tracer.SetOrigin(level.Vec3Offset(pos,z*38),false);
|
tracer.SetOrigin(level.Vec3Offset(pos,z*38),false);
|
||||||
if ( !deathmatch ) return;
|
if ( !deathmatch )
|
||||||
|
{
|
||||||
|
if ( !master || !master.player ) bFRIENDLY = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ( master && master.player ) tracer.SetFriendPlayer(master.player);
|
if ( master && master.player ) tracer.SetFriendPlayer(master.player);
|
||||||
else tracer.bFRIENDLY = false;
|
else tracer.bFRIENDLY = false;
|
||||||
}
|
}
|
||||||
|
|
@ -2127,3 +2140,340 @@ Class MinigunSentryBase : Actor
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// original fun-size stationary version
|
||||||
|
Class SentryGunItem : UnrealInventory
|
||||||
|
{
|
||||||
|
Default
|
||||||
|
{
|
||||||
|
Tag "$T_OSENTRY";
|
||||||
|
Inventory.Icon "I_OSntry";
|
||||||
|
Inventory.MaxAmount 3;
|
||||||
|
Inventory.PickupMessage "$I_OSENTRY";
|
||||||
|
Inventory.RespawnTics 1050;
|
||||||
|
}
|
||||||
|
override bool Use( bool pickup )
|
||||||
|
{
|
||||||
|
if ( pickup ) return false;
|
||||||
|
Vector3 origin = Owner.Vec2OffsetZ(0,0,Owner.player.viewz);
|
||||||
|
FLineTraceData d;
|
||||||
|
Owner.LineTrace(Owner.angle,90,Owner.pitch,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d);
|
||||||
|
if ( d.HitType != TRACE_HitNone ) origin = d.HitLocation-d.HitDir*20;
|
||||||
|
else origin = d.HitLocation;
|
||||||
|
Owner.LineTrace(0,56,90,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d);
|
||||||
|
origin = d.HitLocation;
|
||||||
|
let a = Spawn("SentryGun",origin);
|
||||||
|
if ( !a.TestMobjLocation() )
|
||||||
|
{
|
||||||
|
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_MSNOROOM"));
|
||||||
|
a.Destroy();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tracer = a;
|
||||||
|
a.master = Owner;
|
||||||
|
a.angle = Owner.angle;
|
||||||
|
a.pitch = 0;
|
||||||
|
a.roll = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
States
|
||||||
|
{
|
||||||
|
Spawn:
|
||||||
|
SENT A -1;
|
||||||
|
Stop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Class SentryGunX : Actor
|
||||||
|
{
|
||||||
|
Default
|
||||||
|
{
|
||||||
|
RenderStyle "Add";
|
||||||
|
+NOGRAVITY;
|
||||||
|
+NOBLOCKMAP;
|
||||||
|
+INTERPOLATEANGLES;
|
||||||
|
}
|
||||||
|
override void Tick()
|
||||||
|
{
|
||||||
|
Super.Tick();
|
||||||
|
if ( !tracer || !tracer.InStateSequence(tracer.CurState,tracer.FindState("Fire")) )
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SetOrigin(tracer.pos,true);
|
||||||
|
angle = tracer.angle;
|
||||||
|
pitch = tracer.pitch;
|
||||||
|
roll = tracer.roll;
|
||||||
|
}
|
||||||
|
States
|
||||||
|
{
|
||||||
|
Spawn:
|
||||||
|
SENF A 2 Bright;
|
||||||
|
TNT1 A 2;
|
||||||
|
SENF C 2 Bright;
|
||||||
|
TNT1 A 2;
|
||||||
|
Stop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Class SentryGun : Actor
|
||||||
|
{
|
||||||
|
int rememberedplayer;
|
||||||
|
Default
|
||||||
|
{
|
||||||
|
Health 50;
|
||||||
|
Mass int.max;
|
||||||
|
Radius 10;
|
||||||
|
Height 24;
|
||||||
|
+SOLID;
|
||||||
|
+SHOOTABLE;
|
||||||
|
+NOBLOOD;
|
||||||
|
+DONTTHRUST;
|
||||||
|
+FRIENDLY;
|
||||||
|
}
|
||||||
|
override void PostBeginPlay()
|
||||||
|
{
|
||||||
|
Super.PostBeginPlay();
|
||||||
|
if ( master && master.player )
|
||||||
|
{
|
||||||
|
SetTag(String.Format(StringTable.Localize("$T_OWNEDOSENTRY"),master.player.GetUserName()));
|
||||||
|
rememberedplayer = master.playernumber();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetTag(StringTable.Localize("$T_OSENTRY"));
|
||||||
|
rememberedplayer = -1;
|
||||||
|
}
|
||||||
|
if ( !deathmatch )
|
||||||
|
{
|
||||||
|
if ( !master || !master.player ) bFRIENDLY = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( master && master.player ) SetFriendPlayer(master.player);
|
||||||
|
else bFRIENDLY = false;
|
||||||
|
}
|
||||||
|
override string GetObituary( Actor victim, Actor inflictor, Name mod, bool playerattack )
|
||||||
|
{
|
||||||
|
if ( victim == master ) return String.Format(StringTable.Localize("$O_OWNOSENTRY"),GetTag());
|
||||||
|
return String.Format(StringTable.Localize("$O_OSENTRY"),GetTag());
|
||||||
|
}
|
||||||
|
override void Tick()
|
||||||
|
{
|
||||||
|
Super.Tick();
|
||||||
|
if ( !master && (rememberedplayer != -1) && playeringame[rememberedplayer] )
|
||||||
|
master = players[rememberedplayer].mo;
|
||||||
|
}
|
||||||
|
bool IsEnemy( Actor a )
|
||||||
|
{
|
||||||
|
if ( !a || !a.bSHOOTABLE || !a.bISMONSTER || (a.Health <= 0) ) return false;
|
||||||
|
if ( deathmatch ) return ((a != master) && (a.master != master));
|
||||||
|
return (!bFRIENDLY || (!a.bFRIENDLY && !a.player));
|
||||||
|
}
|
||||||
|
bool HasTarget()
|
||||||
|
{
|
||||||
|
// check for targets in range
|
||||||
|
let ti = ThinkerIterator.Create("Actor");
|
||||||
|
Actor a;
|
||||||
|
while ( a = Actor(ti.Next()) )
|
||||||
|
{
|
||||||
|
if ( !IsEnemy(a) ) continue;
|
||||||
|
Vector3 x = (cos(angle)*cos(pitch),sin(angle)*cos(pitch),-sin(pitch));
|
||||||
|
Vector3 vecto = level.Vec3Diff(Vec3Offset(0,0,16),a.Vec3Offset(0,0,a.height/2));
|
||||||
|
double distto = vecto.length();
|
||||||
|
Vector3 dirto = vecto/distto;
|
||||||
|
double angleto = atan2(dirto.y,dirto.x);
|
||||||
|
double pitchto = asin(-dirto.z);
|
||||||
|
if ( (distto < 6000) && (dirto dot x > 0.95) && !LineTrace(angleto,distto,pitchto,TRF_THRUACTORS,16) )
|
||||||
|
{
|
||||||
|
target = a;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check for targets in a straight line
|
||||||
|
FLineTraceData d;
|
||||||
|
LineTrace(angle,200,pitch,0,16,data:d);
|
||||||
|
if ( (d.HitType == TRACE_HitActor) && IsEnemy(d.HitActor) )
|
||||||
|
{
|
||||||
|
target = d.HitActor;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
target = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if there's a target and we have ammo, jump to first state (if set)
|
||||||
|
// if there's no target but we still have ammo, jump to second state (if set)
|
||||||
|
// if we have no ammo, jump to third state (if set)
|
||||||
|
void A_SentryGunCheck( statelabel actstate = null, statelabel idlestate = null, statelabel failstate = null )
|
||||||
|
{
|
||||||
|
if ( !(GetAge()%35) ) special1++;
|
||||||
|
if ( (special1 >= 200) && failstate ) SetStateLabel(failstate);
|
||||||
|
else if ( HasTarget() && actstate ) SetStateLabel(actstate);
|
||||||
|
else if ( !HasTarget() && idlestate ) SetStateLabel(idlestate);
|
||||||
|
}
|
||||||
|
void A_SentryGunAttack( statelabel failstate = null )
|
||||||
|
{
|
||||||
|
special1++;
|
||||||
|
if ( ((special1 >= 200) || !HasTarget()) && failstate )
|
||||||
|
{
|
||||||
|
A_StopSound(CHAN_BODY);
|
||||||
|
SetStateLabel(failstate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
A_AlertMonsters(0,AMF_TARGETEMITTER);
|
||||||
|
A_PlaySound("sentry/fire",CHAN_WEAPON,pitch:1.6);
|
||||||
|
Vector3 x, y, z, origin;
|
||||||
|
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
|
||||||
|
origin = level.Vec3Offset(pos,x*12+z*16);
|
||||||
|
double a = FRandom[Sentry](0,360), s = FRandom[Sentry](0,0.05);
|
||||||
|
Vector3 nx = target?Vec3To(target).unit():x;
|
||||||
|
Vector3 dir = (nx+y*cos(a)*s+z*sin(a)*s).unit();
|
||||||
|
FLineTraceData d;
|
||||||
|
LineTrace(atan2(dir.y,dir.x),10000,asin(-dir.z),TRF_ABSPOSITION,origin.z,origin.x,origin.y,d);
|
||||||
|
if ( d.HitType == TRACE_HitActor )
|
||||||
|
{
|
||||||
|
int dmg = Random[OSentry](6,17);
|
||||||
|
dmg = d.HitActor.DamageMobj(self,self,dmg,'shot',DMG_USEANGLE|DMG_THRUSTLESS,atan2(d.HitDir.y,d.HitDir.x));
|
||||||
|
double mm = 3000;
|
||||||
|
if ( FRandom[OSentry](0,1) < 0.2 ) mm *= 5;
|
||||||
|
UTMainHandler.DoKnockback(d.HitActor,d.HitDir,mm);
|
||||||
|
if ( d.HitActor.bNOBLOOD )
|
||||||
|
{
|
||||||
|
let p = Spawn("BulletImpact",d.HitLocation);
|
||||||
|
p.angle = atan2(d.HitDir.y,d.HitDir.x)+180;
|
||||||
|
p.pitch = asin(d.HitDir.z);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d.HitActor.TraceBleed(dmg,self);
|
||||||
|
d.HitActor.SpawnBlood(d.HitLocation,atan2(d.HitDir.y,d.HitDir.x)+180,dmg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( d.HitType != TRACE_HitNone )
|
||||||
|
{
|
||||||
|
Vector3 hitnormal = -d.HitDir;
|
||||||
|
if ( d.HitType == TRACE_HitFloor ) hitnormal = d.HitSector.floorplane.Normal;
|
||||||
|
else if ( d.HitType == TRACE_HitCeiling ) hitnormal = d.HitSector.ceilingplane.Normal;
|
||||||
|
else if ( d.HitType == TRACE_HitWall )
|
||||||
|
{
|
||||||
|
hitnormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
|
||||||
|
if ( !d.LineSide ) hitnormal *= -1;
|
||||||
|
}
|
||||||
|
let p = Spawn("BulletImpact",d.HitLocation+hitnormal*0.01);
|
||||||
|
p.angle = atan2(hitnormal.y,hitnormal.x);
|
||||||
|
p.pitch = asin(-hitnormal.z);
|
||||||
|
if ( d.HitLine ) d.HitLine.RemoteActivate(self,d.LineSide,SPAC_Impact,d.HitLocation);
|
||||||
|
}
|
||||||
|
for ( int i=0; i<3; i++ )
|
||||||
|
{
|
||||||
|
let s = Spawn("UTSmoke",origin);
|
||||||
|
s.alpha *= 0.5;
|
||||||
|
s.scale *= 0.7;
|
||||||
|
s.vel += x*2;
|
||||||
|
}
|
||||||
|
let c = Spawn("UCasing",level.Vec3Offset(pos,-x*8+y*0.6+z*16));
|
||||||
|
c.scale *= 0.5;
|
||||||
|
c.vel = x*FRandom[Junk](-1.5,1.5)+y*FRandom[Junk](2,4)+z*FRandom[Junk](2,3);
|
||||||
|
}
|
||||||
|
States
|
||||||
|
{
|
||||||
|
Spawn:
|
||||||
|
SENT A 15;
|
||||||
|
Goto StartUp;
|
||||||
|
StartUp:
|
||||||
|
SENR A 0
|
||||||
|
{
|
||||||
|
A_PlaySound("sentry/raise",pitch:1.6);
|
||||||
|
A_AlertMonsters(0,AMF_TARGETEMITTER);
|
||||||
|
}
|
||||||
|
SENR ABCDE 4;
|
||||||
|
Goto Idle;
|
||||||
|
Idle:
|
||||||
|
SENI A 1 A_SentryGunCheck("WindUp",null,"ShutDown");
|
||||||
|
Wait;
|
||||||
|
WindUp:
|
||||||
|
SENW A 0
|
||||||
|
{
|
||||||
|
A_PlaySound("sentry/wind",looping:true,pitch:1.6);
|
||||||
|
A_AlertMonsters(0,AMF_TARGETEMITTER);
|
||||||
|
}
|
||||||
|
SENW ABCDEFGHIJKLMN 1;
|
||||||
|
Fire:
|
||||||
|
SENF A 0
|
||||||
|
{
|
||||||
|
let f = Spawn("SentryGunX",pos);
|
||||||
|
f.angle = angle;
|
||||||
|
f.pitch = pitch;
|
||||||
|
f.roll = roll;
|
||||||
|
f.tracer = self;
|
||||||
|
}
|
||||||
|
SENF A 2 A_SentryGunAttack("Unwind");
|
||||||
|
SENF B 2;
|
||||||
|
SENF C 2 A_SentryGunAttack("Unwind");
|
||||||
|
SENF D 2;
|
||||||
|
SENU A 0; // tweening hack
|
||||||
|
Loop;
|
||||||
|
Unwind:
|
||||||
|
SENU A 0 A_PlaySound("sentry/unwind",pitch:1.6);
|
||||||
|
SENU ABCDEFGHIJKLMN 1;
|
||||||
|
Goto Idle;
|
||||||
|
ShutDown:
|
||||||
|
SEND A 0 A_PlaySound("sentry/raise",pitch:1.6);
|
||||||
|
SEND ABCDE 4;
|
||||||
|
SEND E 20;
|
||||||
|
SEND E -1 A_Die();
|
||||||
|
Stop;
|
||||||
|
Death:
|
||||||
|
TNT1 A 0
|
||||||
|
{
|
||||||
|
A_StopSound(CHAN_BODY);
|
||||||
|
A_PlaySound("flare/explode",CHAN_VOICE);
|
||||||
|
A_NoGravity();
|
||||||
|
A_Stop();
|
||||||
|
A_SetRenderStyle(1.,STYLE_Add);
|
||||||
|
SetZ(pos.z+16);
|
||||||
|
Spawn("FlareXLight",pos);
|
||||||
|
bMOVEWITHSECTOR = false;
|
||||||
|
bFORCEXYBILLBOARD = true;
|
||||||
|
A_SetScale(FRandomPick[ExploS](-1.5,1.5),FRandomPick[ExploS](-1.5,1.5));
|
||||||
|
int numpt = Random[ExploS](15,30);
|
||||||
|
for ( int i=0; i<numpt; i++ )
|
||||||
|
{
|
||||||
|
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,3);
|
||||||
|
let s = Spawn("UTSmoke",pos);
|
||||||
|
s.vel = pvel;
|
||||||
|
}
|
||||||
|
numpt = Random[ExploS](9,18);
|
||||||
|
for ( int i=0; i<numpt; i++ )
|
||||||
|
{
|
||||||
|
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,6);
|
||||||
|
let s = Spawn("UTSpark",pos);
|
||||||
|
s.vel = pvel;
|
||||||
|
}
|
||||||
|
numpt = Random[ExploS](18,28);
|
||||||
|
for ( int i=0; i<numpt; i++ )
|
||||||
|
{
|
||||||
|
Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](2,12);
|
||||||
|
let s = Spawn("UTChip",pos);
|
||||||
|
s.vel = pvel;
|
||||||
|
s.scale *= FRandom[ExploS](0.9,2.7);
|
||||||
|
}
|
||||||
|
return A_Jump(256,"Explo1","Explo2","Explo3","Explo4","Explo5");
|
||||||
|
}
|
||||||
|
Explo1:
|
||||||
|
EXP1 ABCDEFGH 3 Bright;
|
||||||
|
Stop;
|
||||||
|
Explo2:
|
||||||
|
EXP2 ABCDEFGH 3 Bright;
|
||||||
|
Stop;
|
||||||
|
Explo3:
|
||||||
|
EXP3 ABCDEFGH 3 Bright;
|
||||||
|
Stop;
|
||||||
|
Explo4:
|
||||||
|
EXP4 ABCDEFGH 3 Bright;
|
||||||
|
Stop;
|
||||||
|
Explo5:
|
||||||
|
EXP5 ABCDEFGH 3 Bright;
|
||||||
|
Stop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -979,7 +979,8 @@ Class UnrealMainHandler : EventHandler
|
||||||
else if ( (e.Replacee == 'InvulnerabilitySphere') || (e.Replacee == 'ArtiInvulnerability') ) e.Replacement = 'PowerShield';
|
else if ( (e.Replacee == 'InvulnerabilitySphere') || (e.Replacee == 'ArtiInvulnerability') ) e.Replacement = 'PowerShield';
|
||||||
else if ( (e.Replacee == 'Berserk') || (e.Replacee == 'ArtiTomeOfPower') )
|
else if ( (e.Replacee == 'Berserk') || (e.Replacee == 'ArtiTomeOfPower') )
|
||||||
{
|
{
|
||||||
if ( !Random[Replacements](0,2) ) e.Replacement = 'WeaponPowerUp';
|
if ( !Random[Replacements](0,9) ) e.Replacement = 'SentryItem';
|
||||||
|
else if ( !Random[Replacements](0,2) ) e.Replacement = 'WeaponPowerUp';
|
||||||
else e.Replacement = 'Amplifier';
|
else e.Replacement = 'Amplifier';
|
||||||
}
|
}
|
||||||
else if ( e.Replacee == 'ArtiEgg' ) e.Replacement = 'VoiceBox';
|
else if ( e.Replacee == 'ArtiEgg' ) e.Replacement = 'VoiceBox';
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue