Peacemaker implemented, with some minor model adjustments.

Fixed ammo bars in hud being positioned incorrectly if a weapon in the slot has no ammo.
Sentries now will also complain if the terrain is too steep or you're trying to deploy them in mid-air.
Adjusted protomag spin animation. Still not perfect but I tried my best.
Guess what: more PNG optimization.
This commit is contained in:
Marisa the Magician 2019-09-15 01:49:30 +02:00
commit e562754f00
43 changed files with 760 additions and 17 deletions

View file

@ -252,13 +252,13 @@ faster by putting in more than one shell at a time.
Standard-issue "room clearing" device manufactured by the Inuit Corporation. Standard-issue "room clearing" device manufactured by the Inuit Corporation.
Primary fire: Deploy the device. Having landed on solid ground, it will open up Primary fire: Deploy the device. Hold to increase the activation delay, up to
and release the rockets one by one after a set delay. 9 seconds. Having landed on solid ground, it will wait and then open up and
release the rockets one by one, after which it will self-destruct. Note that
these rockets will chase after anything that gets close, so keep your distance.
Secondary fire: Adjust the activation delay, up to 9 seconds. Secondary fire: Same as before, but the device will instead self-destruct right
away, causing a much bigger boom.
Note that these rockets will chase after anything that gets close, so keep your
distance.
## Impaler ## Impaler

View file

@ -33,6 +33,7 @@ Doom Tournament (currently the devel branch is required).
- Protomag (slot 2) (replaces pistol) - Protomag (slot 2) (replaces pistol)
- Dual Protomags - Dual Protomags
- Quadshot (slot 3) (replaces shotguns) - Quadshot (slot 3) (replaces shotguns)
- Peacemaker (slot 8) (rare spawn in backpacks)
- Backpack (replaces backpack, identical to Doom Tournament version) - Backpack (replaces backpack, identical to Doom Tournament version)
- Unreal 1 HUD - Unreal 1 HUD
- Translator (has to be spawned in, since it would only be useful for mappers) - Translator (has to be spawned in, since it would only be useful for mappers)
@ -71,7 +72,6 @@ Doom Tournament (currently the devel branch is required).
- Fireblaster (slot 5) (replaces rocket launcher) - Fireblaster (slot 5) (replaces rocket launcher)
- Flamethrower (slot 6) (replaces plasma rifle) - Flamethrower (slot 6) (replaces plasma rifle)
- Impaler (slot 7) (replaces plasma rifle) - Impaler (slot 7) (replaces plasma rifle)
- Peacemaker (slot 8) (rare spawn in backpacks)
- Demolisher (slot 9) (replaces bfg9000) - Demolisher (slot 9) (replaces bfg9000)
- Autocannon (slot 0) (replaces bfg9000) - Autocannon (slot 0) (replaces bfg9000)

View file

@ -87,3 +87,5 @@ server bool sting_bhold = false; // biorifle can be held fully loaded
server bool sting_razoraim = false; // razorjack alt follows aim instead of server bool sting_razoraim = false; // razorjack alt follows aim instead of
// being steered by player rotation // being steered by player rotation
server bool sting_biosplash = false; // biorifle alt splashes like in ut server bool sting_biosplash = false; // biorifle alt splashes like in ut
server bool sting_impalerauto = false; // impaler reloads automatically after
// primary fire

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Before After
Before After

View file

@ -6,9 +6,12 @@ DAMNUM_TYPECOLOR_DAMMO3 = "DamYellow";
DAMNUM_TYPECOLOR_DAMMO4 = "DamOrange"; DAMNUM_TYPECOLOR_DAMMO4 = "DamOrange";
DAMNUM_TYPECOLOR_DAMMO5 = "DamRed"; DAMNUM_TYPECOLOR_DAMMO5 = "DamRed";
DAMNUM_TYPECOLOR_STINGER = "DamTeal"; DAMNUM_TYPECOLOR_STINGER = "DamTeal";
DAMNUM_TYPECOLOR_TARYDIUMCHARGE = "DamTeal";
DAMNUM_TYPECOLOR_EXPLODED = "DamGold"; DAMNUM_TYPECOLOR_EXPLODED = "DamGold";
DAMNUM_TYPECOLOR_STUNNED = "DamLightBlue"; DAMNUM_TYPECOLOR_STUNNED = "DamLightBlue";
DAMNUM_TYPECOLOR_IMPALER = "DamMagenta"; DAMNUM_TYPECOLOR_IMPALER = "DamMagenta";
DAMNUM_TYPECOLOR_PEACEDEATH = "DamGold";
DAMNUM_TYPECOLOR_PEACEBARRELDEATH = "DamGold";
/* Obituaries */ /* Obituaries */
O_DPISTOL = "%o was killed by %k's Dispersion Pistol. What a loser!"; O_DPISTOL = "%o was killed by %k's Dispersion Pistol. What a loser!";
O_AUTOMAG = "%o got gatted by %k's Automag."; O_AUTOMAG = "%o got gatted by %k's Automag.";
@ -28,6 +31,7 @@ O_IMPALER1 = "%o had an explosive taste of %k's Impaler.";
O_IMPALER2 = "%o was cooked alive by %k's Impaler."; O_IMPALER2 = "%o was cooked alive by %k's Impaler.";
O_IMPALERHIT = "%o was pierced by %k's Impaler."; O_IMPALERHIT = "%o was pierced by %k's Impaler.";
O_PEACE = "%o was hunted down by %k's Peacemaker missiles."; O_PEACE = "%o was hunted down by %k's Peacemaker missiles.";
O_PEACEMK = "%o got too close to %k's Peacemaker launcher.";
O_FLAMEGUN = "%o was charred by %k's Fireblaster."; O_FLAMEGUN = "%o was charred by %k's Fireblaster.";
O_FLAMETHROWER = "%o was thoroughly roasted by %k's Flamethrower."; 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.";
@ -41,6 +45,8 @@ 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_STINGERX2 = "%o ate flaming Tarydium death."; O_STINGERX2 = "%o ate flaming Tarydium death.";
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.";
O_SPEACE = "%o got too close to a Peacemaker missile.";
O_SPEACEMK = "%o got too close to a Peacemaker launcher.";
/* Pickup messages */ /* Pickup messages */
I_WPOWERUP = "You got a Dispersion Pistol Powerup."; I_WPOWERUP = "You got a Dispersion Pistol Powerup.";
I_STINGERAMMOL = "You picked up "; I_STINGERAMMOL = "You picked up ";
@ -198,6 +204,8 @@ M_SENTRYDOWN = "Your Minigun Sentry has been destroyed.";
M_SENTRYDRY = "Your Minigun Sentry has run out of ammo."; M_SENTRYDRY = "Your Minigun Sentry has run out of ammo.";
M_SENTRYHIJACK = "Your Minigun 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_MSNOFLOOR = "Cannot deploy Sentry at this height.";
M_MSNOFLAT = "Cannot deploy Sentry on such a steep slope.";
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.";
S_MINHUD = "Health %d Score %d Ammo %d"; S_MINHUD = "Health %d Score %d Ammo %d";
@ -276,6 +284,7 @@ O_IMPALER1 = "%o probó el sabor explosivo del Empalador de %k.";
O_IMPALER2 = "%o fue cocinad@[ao_esp] viv@[ao_esp] por el Empalador de %k."; O_IMPALER2 = "%o fue cocinad@[ao_esp] viv@[ao_esp] por el Empalador de %k.";
O_IMPALERHIT = "%o fue perforad@[ao_esp] por el Empalador de %k."; O_IMPALERHIT = "%o fue perforad@[ao_esp] por el Empalador de %k.";
O_PEACE = "%o fue cazad@[ao_esp] por los misiles Peacemaker de %k."; O_PEACE = "%o fue cazad@[ao_esp] por los misiles Peacemaker de %k.";
O_PEACEMK = "%o se acercó demasiado a la lanzadera Peacemaker de %k.";
O_FLAMEGUN = "%o fue carbonizad@[ao_esp] por el Bláster de Fuego de %k."; O_FLAMEGUN = "%o fue carbonizad@[ao_esp] por el Bláster de Fuego de %k.";
O_FLAMETHROWER = "%o fue asad@[ao_esp] a conciencia por el Lanzallamas de %k."; O_FLAMETHROWER = "%o fue asad@[ao_esp] a conciencia por el Lanzallamas de %k.";
O_BIGGUN = "%k abrió un hoyo a través de %o con el Demoledor."; O_BIGGUN = "%k abrió un hoyo a través de %o con el Demoledor.";
@ -289,6 +298,8 @@ 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_STINGERX2 = "%o tragó muerte ardiente de Tarydium."; O_STINGERX2 = "%o tragó muerte ardiente de Tarydium.";
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.";
O_SPEACE = "%o se acercó demasiado a un misil Peacemaker.";
O_SPEACEMK = "%o se acercó demasiado a una lanzadera Peacemaker.";
/* Pickup messages */ /* Pickup messages */
I_WPOWERUP = "Has obtenido una Mejora para la Pistola de Dispersión."; I_WPOWERUP = "Has obtenido una Mejora para la Pistola de Dispersión.";
I_STINGERAMMOL = "Has recogido "; I_STINGERAMMOL = "Has recogido ";
@ -432,6 +443,8 @@ M_SENTRYDOWN = "Tu Torreta ha sido destruida.";
M_SENTRYDRY = "Tu Torreta se ha quedado sin munición."; M_SENTRYDRY = "Tu Torreta se ha quedado sin munición.";
M_SENTRYHIJACK = "Tu Torreta ha sido hackeada."; M_SENTRYHIJACK = "Tu Torreta ha sido hackeada.";
M_MSNOROOM = "No hay espacio para colocar la Torreta."; M_MSNOROOM = "No hay espacio para colocar la Torreta.";
M_MSNOFLOOR = "No se puede colocar la Torreta a esta altura.";
M_MSNOFLAT = "No se puede colocar la Torreta en una cuesta tan inclinada.";
M_NSTOOFAR = "No se puede retirar la Torreta desde esta distancia."; M_NSTOOFAR = "No se puede retirar la Torreta desde esta distancia.";
M_FFNOROOM = "No hay espacio para activar el Campo de Fuerza."; M_FFNOROOM = "No hay espacio para activar el Campo de Fuerza.";
S_MINHUD = "Salud %d Puntuación %d Munición %d"; S_MINHUD = "Salud %d Puntuación %d Munición %d";

View file

@ -1,3 +1,81 @@
Model "Peacerocket"
{
Path "models"
Model 0 "perock_d.3d"
SurfaceSkin 0 1 "Jpeace1.png"
PitchOffset -90
Scale 0.16 0.192 0.16
USEACTORPITCH
USEACTORROLL
FrameIndex PEAR A 0 0
}
Model "PeaceFragment"
{
Path "models"
Model 0 "sfrag_d.3d"
Skin 0 "Jpeace1.png"
Scale 0.1 0.1 0.12
USEACTORPITCH
USEACTORROLL
FrameIndex CHIP A 0 0
FrameIndex CHIP B 0 1
FrameIndex CHIP C 0 2
FrameIndex CHIP D 0 3
FrameIndex CHIP E 0 4
FrameIndex CHIP F 0 5
}
Model "Peacebarrel"
{
Path "models"
Model 0 "peace_d.3d"
Skin 0 "Jpeace1.png"
ZOffset 10
AngleOffset -45
Scale 0.16 -0.16 0.192
USEACTORPITCH
USEACTORROLL
// unfold
FrameIndex PEAM A 0 0
FrameIndex PEAM B 0 1
FrameIndex PEAM C 0 2
FrameIndex PEAM D 0 3
FrameIndex PEAM E 0 4
FrameIndex PEAM F 0 5
FrameIndex PEAM G 0 6
FrameIndex PEAM H 0 7
FrameIndex PEAM I 0 8
FrameIndex PEAM J 0 9
FrameIndex PEAM K 0 10
FrameIndex PEAM L 0 11
FrameIndex PEAM M 0 12
FrameIndex PEAM N 0 13
FrameIndex PEAM O 0 14
FrameIndex PEAM P 0 15
FrameIndex PEAM Q 0 16
FrameIndex PEAM R 0 17
FrameIndex PEAM S 0 18
FrameIndex PEAM T 0 19
FrameIndex PEAM U 0 20
FrameIndex PEAM V 0 21
FrameIndex PEAM W 0 22
FrameIndex PEAM X 0 23
FrameIndex PEAM Y 0 24
FrameIndex PEAM Z 0 25
FrameIndex PEAM [ 0 26
FrameIndex PEAM \ 0 27
FrameIndex PEAM ] 0 28
// launch
FrameIndex PEAL A 0 29
FrameIndex PEAL B 0 30
FrameIndex PEAL C 0 31
FrameIndex PEAL D 0 32
}
Model "Peacemaker" Model "Peacemaker"
{ {
Path "models" Path "models"
@ -5,7 +83,7 @@ Model "Peacemaker"
Skin 1 "Jpeacehand1_.png" Skin 1 "Jpeacehand1_.png"
RollOffset 90 // normally upright, but it's easier to tell apart from a deployed one this way RollOffset 90 // normally upright, but it's easier to tell apart from a deployed one this way
ZOffset 5 ZOffset 5
Scale 0.16 0.192 0.16 Scale 0.16 -0.192 0.16
FrameIndex PEAP B 1 0 FrameIndex PEAP B 1 0
@ -13,3 +91,68 @@ Model "Peacemaker"
ROTATING ROTATING
FrameIndex PEAP A 1 0 FrameIndex PEAP A 1 0
} }
Model "Peacemaker"
{
Path "models"
Model 0 "peacehand_d.3d"
Skin 0 "Jpeacehand1.png"
AngleOffset -90
Scale 0.1 -0.1 0.1
Offset 7.5 -15 -7.5
// Select
FrameIndex PEAS A 0 0
FrameIndex PEAS B 0 1
FrameIndex PEAS C 0 2
FrameIndex PEAS D 0 3
FrameIndex PEAS E 0 4
FrameIndex PEAS F 0 5
FrameIndex PEAS G 0 6
FrameIndex PEAS H 0 7
FrameIndex PEAS I 0 8
FrameIndex PEAS J 0 9
FrameIndex PEAS K 0 10
FrameIndex PEAS L 0 11
FrameIndex PEAS M 0 12
FrameIndex PEAS N 0 13
FrameIndex PEAS O 0 14
FrameIndex PEAS P 0 15
FrameIndex PEAS Q 0 16
FrameIndex PEAS R 0 17
FrameIndex PEAS S 0 18
FrameIndex PEAS T 0 19
// Idle
FrameIndex PEAI A 0 20
// Down
FrameIndex PEAD A 0 22
FrameIndex PEAD B 0 23
FrameIndex PEAD C 0 24
FrameIndex PEAD D 0 25
FrameIndex PEAD E 0 26
FrameIndex PEAD F 0 27
FrameIndex PEAD G 0 28
FrameIndex PEAD H 0 29
FrameIndex PEAD I 0 30
// Throw
FrameIndex PEAF A 0 32
FrameIndex PEAF B 0 33
FrameIndex PEAF C 0 34
FrameIndex PEAF D 0 35
FrameIndex PEAF E 0 36
FrameIndex PEAF F 0 37
FrameIndex PEAF G 0 38
FrameIndex PEAF H 0 39
FrameIndex PEAF I 0 40
// Count (0-9)
FrameIndex PEAC A 0 43
FrameIndex PEAC B 0 44
FrameIndex PEAC C 0 45
FrameIndex PEAC D 0 46
FrameIndex PEAC E 0 47
FrameIndex PEAC F 0 48
FrameIndex PEAC G 0 49
FrameIndex PEAC H 0 50
FrameIndex PEAC I 0 51
FrameIndex PEAC J 0 52
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7 KiB

After

Width:  |  Height:  |  Size: 6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Before After
Before After

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Before After
Before After

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -255,6 +255,14 @@ betamag/slide oldmage
betamag/whip oldawhip betamag/whip oldawhip
betamag/hit oldahit betamag/hit oldahit
peace/select peacesel
peace/up peaceup
peace/set peaceset
peace/down peacedn
peace/throw peacethr
peace/open peaceopn
peace/fly brufly1
translator/event transa3 translator/event transa3
detector/start detact detector/start detact

BIN
sounds/Brufly1.ogg Normal file

Binary file not shown.

BIN
sounds/PeaceOpn.ogg Normal file

Binary file not shown.

BIN
sounds/PeaceSel.ogg Normal file

Binary file not shown.

BIN
sounds/PeaceThr.ogg Normal file

Binary file not shown.

BIN
sprites/PFLAA0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View file

@ -28,3 +28,15 @@ DamageType TarydiumCharge
// obituary for no instigator // obituary for no instigator
Obituary = "$O_STINGERX2" Obituary = "$O_STINGERX2"
} }
DamageType PeaceDeath
{
// obituary for no instigator
Obituary = "$O_SPEACE"
}
DamageType PeaceBarrelDeath
{
// obituary for no instigator
Obituary = "$O_SPEACEMK"
}

View file

@ -1527,9 +1527,28 @@ Class SentryItem : UnrealInventory
} }
Vector3 origin = Owner.Vec2OffsetZ(0,0,Owner.player.viewz); Vector3 origin = Owner.Vec2OffsetZ(0,0,Owner.player.viewz);
FLineTraceData d; FLineTraceData d;
Owner.LineTrace(Owner.angle,90,Owner.pitch,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d); Owner.LineTrace(Owner.angle,80,Owner.pitch,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d);
if ( d.HitType != TRACE_HitNone ) origin = d.HitLocation-d.HitDir*20; if ( d.HitType != TRACE_HitNone )
else origin = d.HitLocation; {
Vector3 normal = -d.HitDir;
if ( d.HitType == TRACE_HitFloor )
{
if ( d.Hit3DFloor ) normal = -d.Hit3DFloor.top.Normal;
else normal = d.HitSector.floorplane.Normal;
}
else if ( d.HitType == TRACE_HitCeiling )
{
if ( d.Hit3DFloor ) normal = -d.Hit3DFloor.bottom.Normal;
else normal = d.HitSector.ceilingplane.Normal;
}
else if ( d.HitType == TRACE_HitWall )
{
normal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
if ( !d.LineSide ) normal *= -1;
}
origin = d.HitLocation+normal*20;
}
else origin = d.HitLocation-d.HitDir*20;
Owner.LineTrace(0,56,90,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d); Owner.LineTrace(0,56,90,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d);
origin = d.HitLocation; origin = d.HitLocation;
let a = Spawn("MinigunSentryBase",origin); let a = Spawn("MinigunSentryBase",origin);
@ -1539,6 +1558,28 @@ Class SentryItem : UnrealInventory
a.Destroy(); a.Destroy();
return false; return false;
} }
if ( a.pos.z-a.floorz > 50 )
{
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_MSNOFLOOR"));
a.Destroy();
return false;
}
F3DFloor ff = null;
for ( int i=0; i<a.floorsector.Get3DFloorCount(); i++ )
{
if ( a.floorsector.Get3DFloor(i).top.ZAtPoint(pos.xy) > floorz ) continue;
ff = a.floorsector.Get3DFLoor(i);
break;
}
Vector3 normal;
if ( ff ) normal = -ff.top.Normal;
else normal = a.floorsector.floorplane.Normal;
if ( normal.z < 0.9 )
{
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_MSNOFLAT"));
a.Destroy();
return false;
}
bActive = true; bActive = true;
bUNTOSSABLE = true; bUNTOSSABLE = true;
bUNDROPPABLE = true; bUNDROPPABLE = true;
@ -2213,9 +2254,28 @@ Class SentryGunItem : UnrealInventory
if ( pickup ) return false; if ( pickup ) return false;
Vector3 origin = Owner.Vec2OffsetZ(0,0,Owner.player.viewz); Vector3 origin = Owner.Vec2OffsetZ(0,0,Owner.player.viewz);
FLineTraceData d; FLineTraceData d;
Owner.LineTrace(Owner.angle,90,Owner.pitch,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d); Owner.LineTrace(Owner.angle,60,Owner.pitch,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d);
if ( d.HitType != TRACE_HitNone ) origin = d.HitLocation-d.HitDir*20; if ( d.HitType != TRACE_HitNone )
else origin = d.HitLocation; {
Vector3 normal = -d.HitDir;
if ( d.HitType == TRACE_HitFloor )
{
if ( d.Hit3DFloor ) normal = -d.Hit3DFloor.top.Normal;
else normal = d.HitSector.floorplane.Normal;
}
else if ( d.HitType == TRACE_HitCeiling )
{
if ( d.Hit3DFloor ) normal = -d.Hit3DFloor.bottom.Normal;
else normal = d.HitSector.ceilingplane.Normal;
}
else if ( d.HitType == TRACE_HitWall )
{
normal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
if ( !d.LineSide ) normal *= -1;
}
origin = d.HitLocation+normal*20;
}
else origin = d.HitLocation-d.HitDir*20;
Owner.LineTrace(0,56,90,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d); Owner.LineTrace(0,56,90,TRF_ABSPOSITION,origin.z,origin.x,origin.y,data:d);
origin = d.HitLocation; origin = d.HitLocation;
let a = Spawn("SentryGun",origin); let a = Spawn("SentryGun",origin);
@ -2225,6 +2285,28 @@ Class SentryGunItem : UnrealInventory
a.Destroy(); a.Destroy();
return false; return false;
} }
if ( a.pos.z-a.floorz > 50 )
{
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_MSNOFLOOR"));
a.Destroy();
return false;
}
F3DFloor ff = null;
for ( int i=0; i<a.floorsector.Get3DFloorCount(); i++ )
{
if ( a.floorsector.Get3DFloor(i).top.ZAtPoint(pos.xy) > floorz ) continue;
ff = a.floorsector.Get3DFLoor(i);
break;
}
Vector3 normal;
if ( ff ) normal = -ff.top.Normal;
else normal = a.floorsector.floorplane.Normal;
if ( normal.z < 0.9 )
{
if ( Owner.CheckLocalView() ) Console.Printf(StringTable.Localize("$M_MSNOFLAT"));
a.Destroy();
return false;
}
tracer = a; tracer = a;
a.master = Owner; a.master = Owner;
a.angle = Owner.angle; a.angle = Owner.angle;

View file

@ -4,22 +4,434 @@ Class PeaceAmmo : Ammo
{ {
Inventory.Icon "I_Peace"; Inventory.Icon "I_Peace";
Inventory.Amount 1; Inventory.Amount 1;
Inventory.MaxAmount 8; Inventory.MaxAmount 1;
Ammo.BackpackAmount 0; Ammo.BackpackAmount 0;
Ammo.BackpackMaxAmount 16; Ammo.BackpackMaxAmount 2;
}
}
Class PeaceTrail : Actor
{
Default
{
RenderStyle "Add";
Radius 0.1;
Height 0;
+NOBLOCKMAP;
+NOGRAVITY;
+DONTSPLASH;
+FORCEXYBILLBOARD;
+NOTELEPORT;
Scale 0.25;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
A_AttachLight('RocketLight',DynamicLight.PointLight,Color(255,128,112),32,32);
}
override void Tick()
{
Super.Tick();
if ( !target || !target.bMISSILE )
{
A_RemoveLight('RocketLight');
Destroy();
return;
}
Vector3 dir = (cos(target.angle)*cos(target.pitch),sin(target.angle)*cos(target.pitch),-sin(target.pitch));
SetOrigin(level.Vec3Offset(target.pos,-dir*3),true);
}
States
{
Spawn:
PFLA A -1 Bright;
Stop;
} }
} }
Class PeaceRocket : Actor Class PeaceRocket : Actor
{ {
Vector3 Acceleration;
int ticcnt;
Default
{
Obituary "$O_PEACE";
DamageType 'PeaceDeath';
Radius 2;
Height 2;
Speed 3.5;
PROJECTILE;
+SKYEXPLODE;
+EXPLODEONWATER;
+SEEKERMISSILE;
+FORCERADIUSDMG;
+NODAMAGETHRUST;
+INTERPOLATEANGLES;
+HITOWNER;
ReactionTime 9;
}
override void PostBeginPlay()
{
Super.PostBeginPlay();
let l = Spawn("PeaceTrail",pos);
l.target = self;
A_PlaySound("peace/fly",CHAN_VOICE,1.0,true,2.5,pitch:0.8);
Acceleration = vel*1.67;
}
action void A_CheckForTargets()
{
let bi = BlockThingsIterator.Create(self,500);
while ( bi.Next() )
{
if ( !bi.Thing || (!bi.Thing.bISMONSTER && !bi.Thing.player) || (bi.Thing.Health <= 0) || (Distance3D(bi.Thing) > 500) || !CheckSight(bi.Thing) ) continue;
tracer = bi.Thing;
return;
}
}
action void A_SeekTargets()
{
if ( !tracer || (tracer.Health <= 0) ) return;
double mag = vel.length();
vel = mag*(level.Vec3Diff(pos,tracer.Vec3Offset(0,0,tracer.height/2)).unit()*mag*6./TICRATE+vel).unit();
}
action void A_PeaceExplode()
{
bFORCEXYBILLBOARD = true;
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("RocketBlast",50);
A_NoGravity();
A_SetScale(1.1);
UTMainHandler.DoBlast(self,200,70000);
A_Explode(100,200);
A_QuakeEx(3,3,3,8,0,250,"",QF_RELATIVE|QF_SCALEDOWN,falloff:200,rollIntensity:0.2);
A_PlaySound("utrl/explode",CHAN_VOICE);
A_AlertMonsters();
Spawn("RocketExplLight",pos);
int numpt = Random[Peace](15,30);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Peace](-1,1),FRandom[Peace](-1,1),FRandom[Peace](-1,1)).unit()*FRandom[Peace](1,3);
let s = Spawn("UTSmoke",pos);
s.vel = pvel;
}
numpt = Random[Peace](10,20);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Peace](-1,1),FRandom[Peace](-1,1),FRandom[Peace](-1,1)).unit()*FRandom[Peace](2,6);
let s = Spawn("UTSpark",pos);
s.vel = pvel;
}
numpt = Random[Peace](35,70);
for ( int i=0; i<numpt; i++ )
{
Vector3 pvel = (FRandom[Peace](-1,1),FRandom[Peace](-1,1),FRandom[Peace](-1,1)).unit()*FRandom[Peace](2,12);
let s = Spawn("UTChip",pos);
s.vel = pvel;
s.scale *= FRandom[Peace](0.9,2.7);
}
}
States
{
Spawn:
PEAR A 1
{
roll += 5.;
A_SeekTargets();
vel += Acceleration/TICRATE;
double mag = vel.length();
if ( mag > 0. )
{
Vector3 dir = vel/mag;
if ( mag > 16 ) vel = vel.unit()*16;
angle = atan2(dir.y,dir.x);
pitch = asin(-dir.z);
mag = Acceleration.length();
Acceleration = dir*mag;
}
for ( int i=0; i<3; i++ )
{
let s = Spawn("UTSmoke",pos);
s.vel = (FRandom[Peace](-0.2,0.2),FRandom[Peace](-0.2,0.2),FRandom[Peace](-0.2,0.2));
s.vel += vel*0.1;
s.SetShade(Color(1,1,1)*Random[Peace](32,48));
}
special1++;
if ( special1 > 35 )
{
special1 = 0;
A_CheckForTargets();
A_CountDown();
}
}
Wait;
Death:
TNT1 A 0 A_PeaceExplode();
SSMX ABCDEFGHIJ 2 Bright;
Stop;
}
} }
Class PeaceProj : Actor Class PeaceFragment : SentryFragment
{ {
Default
{
Scale 0.5;
}
}
Class PeaceBarrel : Actor
{
action void A_AlignSelf()
{
// find closest 3d floor for its normal
F3DFloor ff = null;
for ( int i=0; i<floorsector.Get3DFloorCount(); i++ )
{
if ( !(floorsector.Get3DFloor(i).top.ZAtPoint(pos.xy) ~== floorz) ) continue;
ff = floorsector.Get3DFLoor(i);
break;
}
Vector3 normal;
if ( ff ) normal = -ff.top.Normal;
else normal = floorsector.floorplane.Normal;
// bless Gutawer
Vector2 angv = (cos(angle),sin(angle));
Vector3 x;
if ( ff ) x = (angv,ff.top.ZAtPoint(pos.xy+angv)-pos.z).unit();
else x = (angv,floorsector.floorplane.ZAtPoint(pos.xy+angv)-pos.z).unit();
pitch = -asin(x.z);
roll = asin(normal.x*angv.y-normal.y*angv.x);
}
action void A_FireRocket( int n )
{
A_PlaySound("flak/altfire",CHAN_AUTO);
A_AlertMonsters();
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 dir = z*1.3;
Vector3 origin;
switch ( n )
{
case 0:
// front right
dir = (dir+x+y).unit();
origin = level.Vec3Offset(pos,z*4+x*4+y*4);
break;
case 1:
// front left
dir = (dir-x+y).unit();
origin = level.Vec3Offset(pos,z*4-x*4+y*4);
break;
case 2:
// back right
dir = (dir+x-y).unit();
origin = level.Vec3Offset(pos,z*4+x*4-y*4);
break;
case 3:
// back left
dir = (dir-x-y).unit();
origin = level.Vec3Offset(pos,z*4-x*4-y*4);
break;
}
let r = Spawn("PeaceRocket",origin);
r.angle = atan2(dir.y,dir.x);
r.pitch = asin(-dir.z);
r.vel = dir*r.speed;
r.target = target;
}
action void A_BlowUp()
{
bFORCEXYBILLBOARD = true;
SetOrigin(Vec3Offset(0,0,16),false);
A_SetRenderStyle(1.0,STYLE_Add);
A_SprayDecal("RocketBlast",50);
A_NoGravity();
A_SetScale(bAMBUSH?1.8:1.2);
A_Explode(bAMBUSH?500:125,bAMBUSH?200:100);
A_PlaySound("sentry/explode",CHAN_BODY,pitch:0.6);
A_PlaySound("utrl/explode",CHAN_VOICE,pitch:0.8);
A_AlertMonsters();
A_QuakeEx(4,4,4,10,0,400,"",QF_RELATIVE|QF_SCALEDOWN,falloff:300,rollIntensity:0.2);
UTMainHandler.DoBlast(self,bAMBUSH?200:100,50000);
double ang, pt;
for ( int i=0; i<16; i++ )
{
let f = Spawn("PeaceFragment",Vec3Offset(FRandom[EFrag](-8,8),FRandom[EFrag](-8,8),FRandom[EFrag](4,12)));
ang = FRandom[EFrag](0,360);
pt = FRandom[EFrag](-90,90);
f.vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[EFrag](4,20);
f.vel.z += 3.;
}
int numpt = Random[ExploS](20,35);
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,9);
let s = Spawn("UTSmoke",pos);
s.vel = pvel;
s.scale *= 2.;
}
numpt = Random[ExploS](10,20);
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](20,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](2,12);
let s = Spawn("UTChip",pos);
s.vel = pvel;
s.scale *= FRandom[ExploS](0.9,2.7);
}
Spawn("FlareXLight",pos);
}
Default
{
Obituary "$O_PEACEMK";
Radius 6;
Height 9;
DamageType 'PeaceBarrelDeath';
PROJECTILE;
-NOGRAVITY;
+SKYEXPLODE;
+FORCERADIUSDMG;
+NODAMAGETHRUST;
+MOVEWITHSECTOR;
+CANBOUNCEWATER;
+BOUNCEAUTOOFF;
+BOUNCEAUTOOFFFLOORONLY;
+USEBOUNCESTATE;
+INTERPOLATEANGLES;
Speed 8;
BounceType "Hexen";
BounceFactor 0.3; // otherwise it's too damn bouncy
BounceSound "transloc/bounce";
WallBounceFactor 0.8;
Gravity 0.35;
}
States
{
Spawn:
PEAM A -1;
Stop;
Bounce:
PEAM A 0
{
if ( BlockingFloor ) A_AlignSelf();
else pitch = roll = 0;
if ( vel.length() < 2. ) ClearBounce();
}
Goto Spawn;
Death:
PEAM A 1 A_CheckFloor(1);
Wait;
PEAM A 4 A_AlignSelf();
PEAM A 35
{
A_PlaySound((special1<=0)?"utrl/seeklost":"utrl/seeklock",CHAN_AUTO);
A_AlertMonsters();
return A_JumpIf(--special1<0,1);
}
Wait;
PEAM A 0 A_JumpIf(bAMBUSH,"Detonate");
PEAM A 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEAM B 3;
PEAM C 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEAM D 3 A_PlaySound("transloc/bounce",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEAM E 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEAM F 3
{
A_PlaySound("transloc/bounce",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
A_PlaySound("transloc/bounce",CHAN_AUTO,.5,pitch:FRandom[Peace](0.8,1.2));
}
PEAM G 3 A_PlaySound("peace/open",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
PEAM H 3
{
A_PlaySound("transloc/bounce",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
A_PlaySound("transloc/bounce",CHAN_AUTO,.5,pitch:FRandom[Peace](0.8,1.2));
}
PEAM I 3;
PEAM J 3
{
A_PlaySound("transloc/bounce",CHAN_AUTO,.8,pitch:FRandom[Peace](0.8,1.2));
A_PlaySound("transloc/bounce",CHAN_AUTO,.5,pitch:FRandom[Peace](0.8,1.2));
}
PEAM K 3 A_PlaySound("utrl/rotate",CHAN_AUTO,.1);
PEAM L 3 A_PlaySound("transloc/bounce",CHAN_AUTO,.5,pitch:FRandom[Peace](0.8,1.2));
PEAM M 3;
PEAM N 3 A_PlaySound("utrl/rotate",CHAN_AUTO,.1);
PEAM OPQ 3;
PEAM R 3 A_PlaySound("utrl/rotate",CHAN_AUTO,.1);
PEAM STU 3;
PEAM V 3 A_PlaySound("utrl/rotate",CHAN_AUTO,.1);
PEAM XYZ[\] 3;
PEAM ] 35;
PEAM ] 0 A_FireRocket(0);
PEAL A 20;
PEAL A 0 A_FireRocket(1);
PEAL B 20;
PEAL B 0 A_FireRocket(2);
PEAL C 20;
PEAL C 0 A_FireRocket(3);
PEAL D 20;
Detonate:
PEAM A 20;
BlowUp:
TNT1 A 0 A_BlowUp();
SSMX ABCDEFGHIJ 2 Bright;
Stop;
}
} }
Class Peacemaker : UnrealWeapon Class Peacemaker : UnrealWeapon
{ {
action void A_PeacemakerThrow( bool bAlt = false )
{
let weap = Weapon(invoker);
if ( weap.Ammo1.Amount <= 0 ) return;
if ( !weap.DepleteAmmo(weap.bAltFire,true,1) ) return;
invoker.FireEffect();
A_PlaySound("peace/throw",CHAN_WEAPON);
Vector3 x, y, z;
[x, y, z] = dt_CoordUtil.GetAxes(pitch,angle,roll);
Vector3 origin = level.Vec3Offset(Vec2OffsetZ(0,0,player.viewz),10*x+y*5-z*3);
let p = Spawn("PeaceBarrel",origin);
if ( bAlt ) p.bAMBUSH = true;
p.special1 = invoker.special2;
p.angle = angle;
p.pitch = BulletSlope();
p.vel = (cos(p.angle)*cos(p.pitch),sin(p.angle)*cos(p.pitch),-sin(p.pitch))*p.speed;
p.vel.z += 2.;
p.target = self;
if ( weap.Ammo1.Amount <= 0 ) player.SetPSprite(PSP_WEAPON,invoker.FindState("EmptyIdle"));
else player.SetPSprite(PSP_WEAPON,invoker.FindState("Ready"));
}
action void A_StartCount()
{
invoker.special1 = invoker.special2 = 0;
A_PlaySound("peace/set",CHAN_ITEM,.4);
}
action void A_CountUp( Statelabel next )
{
invoker.special1++;
if ( invoker.special1 > 20 )
{
invoker.special2++;
if ( invoker.special2 <= 9 )
{
A_PlaySound("peace/set",CHAN_ITEM,.4);
player.FindPSprite(PSP_WEAPON).frame = invoker.special2;
}
invoker.special1 = 0;
}
if ( (invoker.special2 >= 10) || !(player.cmd.buttons&(BT_ATTACK|BT_ALTATTACK)) )
{
invoker.special2 = min(9,invoker.special2);
player.SetPSprite(PSP_WEAPON,invoker.FindState(next));
}
}
Default Default
{ {
Tag "$T_PEACE"; Tag "$T_PEACE";
@ -29,6 +441,8 @@ Class Peacemaker : UnrealWeapon
Weapon.SelectionOrder 1; Weapon.SelectionOrder 1;
Weapon.AmmoType "PeaceAmmo"; Weapon.AmmoType "PeaceAmmo";
Weapon.AmmoUse 1; Weapon.AmmoUse 1;
Weapon.AmmoType2 "PeaceAmmo";
Weapon.AmmoUse2 1;
Weapon.AmmoGive 1; Weapon.AmmoGive 1;
UTWeapon.DropAmmo 1; UTWeapon.DropAmmo 1;
} }
@ -39,5 +453,73 @@ Class Peacemaker : UnrealWeapon
Stop; Stop;
PEAP B -1; PEAP B -1;
Stop; Stop;
Select:
PEAS A 1 A_Raise(int.max);
Wait;
Ready:
PEAS ABCDEFGHIJ 2 A_WeaponReady(WRF_NOFIRE);
PEAS K 0 A_PlaySound("peace/up",CHAN_ITEM,.4);
PEAS KLMNOPQRST 2 A_WeaponReady(WRF_NOFIRE);
Idle:
PEAI A 1
{
A_CheckReload();
A_WeaponReady();
}
Wait;
EmptyIdle:
TNT1 A 1
{
let weap = Weapon(invoker);
if ( weap.Ammo1.Amount > 0 )
return ResolveState("Ready");
A_CheckReload();
A_WeaponReady(WRF_NOFIRE);
return ResolveState(null);
}
Wait;
Fire:
PEAC A 1 A_StartCount();
PEAC # 1 A_CountUp(1);
Wait;
PEAF ABCD 2;
PEAF E 0
{
A_PlaySound("peace/down",CHAN_ITEM,.4);
UTMainHandler.DoSwing(self,(FRandom[Peace](-0.1,-0.04),FRandom[Peace](0.4,0.6)),3,0,7,SWING_Spring,3,0.8);
}
PEAF EFG 2;
PEAF H 0
{
UTMainHandler.DoSwing(self,(FRandom[Peace](0.08,0.12),FRandom[Peace](-1.2,-0.9)),4,0,6,SWING_Spring,3,1.5);
}
PEAF HI 2; // hello
PEAF I -1 A_PeacemakerThrow();
Stop;
AltFire:
PEAC A 1 A_StartCount();
PEAC # 1 A_CountUp(1);
Wait;
PEAF ABCD 2;
PEAF E 0
{
A_PlaySound("peace/down",CHAN_ITEM,.4);
UTMainHandler.DoSwing(self,(FRandom[Peace](-0.1,-0.04),FRandom[Peace](0.4,0.6)),3,0,7,SWING_Spring,3,0.8);
}
PEAF EFG 2;
PEAF H 0
{
UTMainHandler.DoSwing(self,(FRandom[Peace](0.08,0.12),FRandom[Peace](-1.2,-0.9)),4,0,6,SWING_Spring,3,1.5);
}
PEAF HI 2; // howdy
PEAF I -1 A_PeacemakerThrow(true);
Stop;
Deselect:
PEAD A 0 A_JumpIfNoAmmo("EmptyDeselect");
PEAD ABCDEFGHI 1;
PEAD J 1 A_Lower(int.max);
EmptyDeselect:
TNT1 A 1 A_Lower(int.max);
Wait;
} }
} }

View file

@ -345,6 +345,7 @@ Class UnrealHUD : BaseStatusBar
for ( int j=0; j<aslots[i].Size(); j++ ) for ( int j=0; j<aslots[i].Size(); j++ )
{ {
let amo = aslots[i][j]; let amo = aslots[i][j];
if ( amo.Amount <= 0 ) continue;
AmmoBarSize = 16*min(1.0,amo.Amount/double(amo.MaxAmount)); AmmoBarSize = 16*min(1.0,amo.Amount/double(amo.MaxAmount));
CurX = HalfHUDX-3+realslot*6+(4./nammo)*cbar; CurX = HalfHUDX-3+realslot*6+(4./nammo)*cbar;
CurY = HalfHUDY+29-AmmoBarSize; CurY = HalfHUDY+29-AmmoBarSize;