From b347f65c3b632586eb36f1e2b9776daf84bf758c Mon Sep 17 00:00:00 2001 From: Lemon-King Date: Tue, 24 Oct 2023 02:04:25 -0400 Subject: [PATCH] Paladin: Fix numerous bugs with Vorpal Sword, Fix Axe projectiles Added LemonUtil Velocity to Eular Angles to properly update facing for MD3s in real time --- .../actors/hxdd/hexen2/spritefx/_spritefx.zs | 2 + .../hxdd/hexen2/spritefx/blueexplosion.zs | 13 ++ .../hxdd/hexen2/spritefx/smallblueflash.zs | 12 ++ .../hxdd/hexen2/spritefx/smallexplosion.zs | 5 + .../actors/hxdd/hexen2/weapons/paladinaxe.zs | 74 ++++--- .../hxdd/hexen2/weapons/paladinpurifier.zs | 10 + .../hxdd/hexen2/weapons/paladinvorpalsword.zs | 187 +++++++++++++----- 7 files changed, 228 insertions(+), 75 deletions(-) create mode 100644 resources/assets/zscript/actors/hxdd/hexen2/spritefx/blueexplosion.zs create mode 100644 resources/assets/zscript/actors/hxdd/hexen2/spritefx/smallblueflash.zs diff --git a/resources/assets/zscript/actors/hxdd/hexen2/spritefx/_spritefx.zs b/resources/assets/zscript/actors/hxdd/hexen2/spritefx/_spritefx.zs index f706df9..2cb303b 100644 --- a/resources/assets/zscript/actors/hxdd/hexen2/spritefx/_spritefx.zs +++ b/resources/assets/zscript/actors/hxdd/hexen2/spritefx/_spritefx.zs @@ -42,6 +42,7 @@ class SpriteFXParticle: ActorParticle { #include "zscript/actors/hxdd/hexen2/spritefx/acidexplosion2.zs" #include "zscript/actors/hxdd/hexen2/spritefx/acidmuzzleflash.zs" #include "zscript/actors/hxdd/hexen2/spritefx/bigexplosion.zs" +#include "zscript/actors/hxdd/hexen2/spritefx/blueexplosion.zs" #include "zscript/actors/hxdd/hexen2/spritefx/fireboom.zs" #include "zscript/actors/hxdd/hexen2/spritefx/firecircle.zs" #include "zscript/actors/hxdd/hexen2/spritefx/firewall1.zs" @@ -51,6 +52,7 @@ class SpriteFXParticle: ActorParticle { #include "zscript/actors/hxdd/hexen2/spritefx/firewall5.zs" #include "zscript/actors/hxdd/hexen2/spritefx/flamestream.zs" #include "zscript/actors/hxdd/hexen2/spritefx/pow.zs" +#include "zscript/actors/hxdd/hexen2/spritefx/smallblueflash.zs" #include "zscript/actors/hxdd/hexen2/spritefx/smallexplosion.zs" #include "zscript/actors/hxdd/hexen2/spritefx/smallwhiteflash.zs" #include "zscript/actors/hxdd/hexen2/spritefx/sparks.zs" diff --git a/resources/assets/zscript/actors/hxdd/hexen2/spritefx/blueexplosion.zs b/resources/assets/zscript/actors/hxdd/hexen2/spritefx/blueexplosion.zs new file mode 100644 index 0000000..5c46f1a --- /dev/null +++ b/resources/assets/zscript/actors/hxdd/hexen2/spritefx/blueexplosion.zs @@ -0,0 +1,13 @@ +class BlueExplosion : SpriteFX { + Default { + RenderStyle "Add"; + Alpha 0.5; + } + + States { + Spawn: + BLU3 A 2 Bright; + BLU3 BCDEFGHI 2 Bright; + Stop; + } +} \ No newline at end of file diff --git a/resources/assets/zscript/actors/hxdd/hexen2/spritefx/smallblueflash.zs b/resources/assets/zscript/actors/hxdd/hexen2/spritefx/smallblueflash.zs new file mode 100644 index 0000000..866dd98 --- /dev/null +++ b/resources/assets/zscript/actors/hxdd/hexen2/spritefx/smallblueflash.zs @@ -0,0 +1,12 @@ +class SmallBlueFlash : SpriteFX { + Default { + RenderStyle "Add"; + Alpha 0.75; + } + + States { + Spawn: + SMBL ABC 2 Bright; + Stop; + } +} \ No newline at end of file diff --git a/resources/assets/zscript/actors/hxdd/hexen2/spritefx/smallexplosion.zs b/resources/assets/zscript/actors/hxdd/hexen2/spritefx/smallexplosion.zs index e9583a8..f2f37d7 100644 --- a/resources/assets/zscript/actors/hxdd/hexen2/spritefx/smallexplosion.zs +++ b/resources/assets/zscript/actors/hxdd/hexen2/spritefx/smallexplosion.zs @@ -1,5 +1,10 @@ class SmallExplosion: SpriteFX { + Default { + RenderStyle "Add"; + Alpha 0.75; + } + States { Spawn: SMEX ABCDEFGHIJKL 3 Bright; diff --git a/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinaxe.zs b/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinaxe.zs index b575c71..e395c50 100644 --- a/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinaxe.zs +++ b/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinaxe.zs @@ -1,4 +1,6 @@ +// Paladin Weapon: Axe // ref: https://github.com/videogamepreservation/hexen2/blob/master/H2MP/hcode/axe.hc + class PWeapAxe : PaladinWeapon { Default { Weapon.SelectionOrder 1000; @@ -79,7 +81,7 @@ class PWeapAxe : PaladinWeapon { PWeapVorpalSword_MissileWave(SpawnPlayerMissile("PWeapAxe_BladeProjectilePower", angle + angOff, 0, 10, 12)); } else { A_StartSound("hexen2/paladin/axgen"); - PWeapVorpalSword_MissileWave(SpawnPlayerMissile("PWeapAxe_BladeProjectile", angle, 0, 10, 12)); + PWeapAxe_BladeProjectilePower projAxe = PWeapAxe_BladeProjectilePower(SpawnFirstPerson("PWeapAxe_BladeProjectile", angle, 1, -7, true)); } } @@ -146,11 +148,15 @@ class PWeapAxe_BladeProjectileTail: Actor { States { Spawn: TAIL AB 2; - Stop; + Loop; } override void Tick() { Super.Tick(); + + if (!self.target) { + self.Destroy(); + } } } @@ -205,6 +211,14 @@ class PWeapAxe_BladeProjectilePower : PWeapAxe_BladeProjectile { Default { RenderStyle "Add"; } + + override void BeginPlay() { + self.A_ChangeModel(self.GetClassName(), + modelindex: 0, modelpath: "models/", model: "axblade.md3", + skinindex: 0, skinpath: "models/", "axblade_skin1", + generatorindex: 0 + ); + } } class PWeapAxe_BladeProjectile : Hexen2Projectile { @@ -261,23 +275,32 @@ class PWeapAxe_BladeProjectile : Hexen2Projectile { Stop; } + override void PostBeginPlay() { + Super.PostBeginPlay(); + PWeapAxe_BladeProjectileTail tail = PWeapAxe_BladeProjectileTail(Spawn("PWeapAxe_BladeProjectileTail")); + if (tail) { + tail.target = self; + tail.angle = self.angle; + tail.pitch = self.pitch; + tail.roll = self.roll; + tail.SetOrigin(self.pos, false); + self.attachedTail = tail; + } + } + override void Tick() { Super.Tick(); - if (attachedTail) { - attachedTail.angle = self.angle; - attachedTail.pitch = self.pitch; - attachedTail.roll = self.roll; - attachedTail.SetOrigin(self.pos, true); - } else { - PWeapAxe_BladeProjectileTail tail = PWeapAxe_BladeProjectileTail(Spawn("PWeapAxe_BladeProjectileTail")); - if (tail) { - tail.angle = self.angle; - tail.pitch = self.pitch; - tail.roll = self.roll; - tail.SetOrigin(self.pos, false); - attachedTail = tail; - } + Vector3 facing = LemonUtil.GetEularFromVelocity(self.vel); + self.angle = facing.x; + self.pitch = facing.y; + self.roll = facing.z; + + if (self.attachedTail) { + self.attachedTail.angle = self.angle; + self.attachedTail.pitch = self.pitch; + self.attachedTail.roll = self.roll; + self.attachedTail.SetOrigin(self.pos, true); } if (tickDuration <= 0) { @@ -288,26 +311,28 @@ class PWeapAxe_BladeProjectile : Hexen2Projectile { } void A_OnBounce() { + // use lightbringer code for adjustment! + Actor fxHit; A_StartSound("hexen2/weapons/explode", CHAN_WEAPON, CHANF_OVERLAP); if (self is "PWeapAxe_BladeProjectilePower") { - fxHit = Actor(Spawn("PWeapAxe_BladeProjectileExplodePowerHit")); + fxHit = Actor(Spawn("BlueExplosion")); } else { - fxHit = Actor(Spawn("PWeapAxe_BladeProjectileExplodeHit")); + fxHit = Actor(Spawn("SmallExplosion")); } if (fxHit) { fxHit.SetOrigin(self.pos, false); } - bounces++; + self.bounces++; if (tracer && (tracer.bIsMonster || tracer.bShootable)) { - bounces++; + self.bounces++; // doubled on monster hit if (self is "PWeapAxe_BladeProjectilePower") { A_DamageRadius(); } A_DamageHit(); } - if (bounces >= 4) { + if (self.bounces >= 4) { A_DestroySelf(); } } @@ -329,7 +354,12 @@ class PWeapAxe_BladeProjectile : Hexen2Projectile { } void A_DestroySelf() { - Actor fxFade = Actor(Spawn("PWeapAxe_BladeProjectileFade")); + Actor fxFade; + if (self is "PWeapAxe_BladeProjectilePower") { + fxFade = Actor(Spawn("SmallWhiteFlash")); + } else { + fxFade = Actor(Spawn("SmallBlueFlash")); + } if (fxFade) { fxFade.SetOrigin(self.pos, false); } diff --git a/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinpurifier.zs b/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinpurifier.zs index 84e3a14..a18601f 100644 --- a/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinpurifier.zs +++ b/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinpurifier.zs @@ -216,6 +216,11 @@ class PWeapPurifier_Missile: Actor { return; } + Vector3 facing = LemonUtil.GetEularFromVelocity(self.vel); + self.angle = facing.x; + self.pitch = facing.y; + self.roll = facing.z; + self.tickDuration -= 1; if (self.tickDuration <= 0) { self.Destroy(); @@ -310,6 +315,11 @@ class PWeapPurifier_DragonBall: Actor { if (InStateSequence(CurState, self.Findstate("Death"))) { return; } + + Vector3 facing = LemonUtil.GetEularFromVelocity(self.vel); + self.angle = facing.x; + self.pitch = facing.y; + self.roll = facing.z; self.tickDuration -= 1; if (self.tickDuration <= 0) { diff --git a/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinvorpalsword.zs b/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinvorpalsword.zs index 98301be..bff1f08 100644 --- a/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinvorpalsword.zs +++ b/resources/assets/zscript/actors/hxdd/hexen2/weapons/paladinvorpalsword.zs @@ -10,7 +10,7 @@ class PWeapVorpalSword : PaladinWeapon Weapon.YAdjust 0; Weapon.AmmoType1 "Mana1"; Weapon.AmmoUse 0; - Weapon.AmmoGive 100; + Weapon.AmmoGive 25; +BLOODSPLATTER +FLOATBOB +WEAPON.AMMO_OPTIONAL @@ -21,35 +21,34 @@ class PWeapVorpalSword : PaladinWeapon FloatBobStrength 0.25; } - States - { - Spawn: - PKUP A -1; - Stop; - Select: - TNT1 A 0 Offset(0, 32); - PSWA EDCBA 2; - PSWA ABCDEFG 2; - PSWA H 2 A_StartSound("hexen2/weapons/vorpswng"); - PSWA IJKL 2; - PSWA M 2 A_StartSound("hexen2/weapons/vorpswng"); - PSWA NOPQRSTUV 2; - PSWR A 0 A_Raise(100); - Loop; - Deselect: - PSWR A 2 Offset(0, 32); // has a unique blending issue, setting to 2 ticks corrects deselect motion - PSWC ABCDE 2; - TNT1 A 0 A_Lower(100); - Loop; - Ready: - PSWR A 2 A_WeaponReady; - Loop; - Fire: - PSWB A 2; - PSWB B 2 A_SwingSFX; - PSWB C 2 A_Swing; - PSWB DEFGHIJKLM 2; - Goto Ready; + States { + Spawn: + PKUP A -1; + Stop; + Select: + TNT1 A 0 Offset(0, 32); + PSWA EDCBA 2; + PSWA ABCDEFG 2; + PSWA H 2 A_StartSound("hexen2/weapons/vorpswng"); + PSWA IJKL 2; + PSWA M 2 A_StartSound("hexen2/weapons/vorpswng"); + PSWA NOPQRSTUV 2; + PSWR A 0 A_Raise(100); + Loop; + Deselect: + PSWR A 2 Offset(0, 32); // has a unique blending issue, setting to 2 ticks corrects deselect motion + PSWC ABCDE 2; + TNT1 A 0 A_Lower(100); + Loop; + Ready: + PSWR A 2 A_WeaponReady; + Loop; + Fire: + PSWB A 2; + PSWB B 2 A_SwingSFX; + PSWB C 2 A_Swing; + PSWB DEFGHIJKLM 2; + Goto Ready; } override void Tick() { @@ -99,8 +98,11 @@ class PWeapVorpalSword : PaladinWeapon } } if (hasTome && amount > 0) { - PWeapVorpalSword_MissileWave projWave = PWeapVorpalSword_MissileWave(SpawnPlayerMissile("PWeapVorpalSword_MissileWave", angle, 0, 0, 12)); + PWeapVorpalSword_MissileWave projWave = PWeapVorpalSword_MissileWave(SpawnPlayerMissile("PWeapVorpalSword_MissileWave", angle, 0, 0, 7)); if (projWave) { + projWave.angle = Player.mo.angle; + projWave.pitch = Player.mo.pitch; + projWave.roll = Player.mo.roll; projWave.waveType = weaponspecial; weaponspecial++; if (weaponspecial > 1) { @@ -125,14 +127,7 @@ class PWeapVorpalSword : PaladinWeapon // spawn swipe PWeapVorpalSword_Swipe swipe = PWeapVorpalSword_Swipe(Spawn("PWeapVorpalSword_Swipe")); if (swipe) { - swipe.playerInfo = player; - swipe.target = player.mo; - swipe.angle = swipe.target.angle; - swipe.pitch = swipe.target.pitch; - swipe.roll = swipe.target.roll; - - Vector3 pos = (swipe.target.pos.x, swipe.target.pos.y - (sin(angle) * 10), player.viewz - (cos(angle) * 10)); - swipe.SetOrigin(pos, true); + swipe.SetOwner(player); fx = "SmallWhiteFlashSFX"; } @@ -178,7 +173,7 @@ class PWeapVorpalSword : PaladinWeapon } class PWeapVorpalSword_Swipe : Actor { - PlayerInfo playerInfo; + PlayerInfo owner; Default { @@ -204,14 +199,41 @@ class PWeapVorpalSword_Swipe : Actor { Super.BeginPlay(); } + override void PostBeginPlay() { + Super.PostBeginPlay(); + + self.UpdateOrigin(); + } + override void Tick() { Super.Tick(); - angle = self.target.angle; - pitch = self.target.pitch; - roll = self.target.roll; + self.UpdateOrigin(); + } + + void SetOwner(PlayerInfo p) { + self.owner = p; + self.target = self.owner.mo; + self.angle = self.target.angle; + self.pitch = self.target.pitch; + self.roll = self.target.roll; + + self.UpdateOrigin(); + } - Vector3 pos = (self.target.pos.x, self.target.pos.y, self.playerInfo.viewz - 10); + void UpdateOrigin() { + self.angle = self.target.angle; + self.pitch = self.target.pitch; + self.roll = self.target.roll; + + double a = self.angle; + double p = Clamp(self.pitch, -90, 90); + double r = self.roll; + let mat = HXDD_GM_Matrix.fromEulerAngles(a, p, r); + mat = mat.multiplyVector3((0, 0, -10)); + vector3 offsetPos = mat.asVector3(false); + + Vector3 pos = (self.target.pos.x, self.target.pos.y, self.owner.viewz) + offsetPos; SetOrigin(pos, true); } } @@ -269,6 +291,7 @@ class PWeapVorpalSword_MissileWaveFX : Actor { } } +// TODO REPLACE WITH CHANGEMODEL class PWeapVorpalSword_MissileWaveA : PWeapVorpalSword_MissileWaveFX { override void Tick() { Super.Tick(); @@ -351,6 +374,11 @@ class PWeapVorpalSword_MissileWave : Hexen2Projectile { tickDuration -= 35.0f / 1000.0f; + Vector3 facing = LemonUtil.GetEularFromVelocity(self.vel); + self.angle = facing.x; + self.pitch = facing.y; + self.roll = facing.z; + //if (!self.tracer) { //TraceSide(-90.0); //TraceSide(90.0); @@ -393,6 +421,7 @@ class PWeapVorpalSword_MissileWave : Hexen2Projectile { shock.roll = self.roll; shock.target = self.target; shock.SetOrigin(self.pos, false); + shock.damageMulti = self.damageMulti; } if (attachedActor[0]) { @@ -443,8 +472,11 @@ class PWeapVorpalSword_Shock : Actor { double tickDuration; property tickDuration: tickDuration; + double damageMulti; int waveType; + int idx; + Default { +NOBLOCKMAP +NOGRAVITY @@ -459,14 +491,13 @@ class PWeapVorpalSword_Shock : Actor { Height 0; Radius 0; - PWeapVorpalSword_Shock.tickDuration 0.75; + PWeapVorpalSword_Shock.tickDuration 0.5 * 35; } - States - { - Spawn: - SHOK AB 1 Bright; - Loop; + States { + Spawn: + SHOK AB 1 Bright; + Loop; } override void BeginPlay() { @@ -475,8 +506,6 @@ class PWeapVorpalSword_Shock : Actor { override void PostBeginPlay() { Super.PostBeginPlay(); - - roll = frandom[shokrng](0.0, 360.0); } override void Tick() { @@ -495,6 +524,58 @@ class PWeapVorpalSword_Shock : Actor { Scale.x = self.Default.Scale.x * frandom[shokrng](0.8, 1.4); Scale.y = self.Default.Scale.y * frandom[shokrng](0.8, 1.4); - tickDuration -= 35.0f / 1000.0f; + self.tickDuration--; + self.idx = (idx + 1) % 2; + if (self.idx == 1 && self.target && self.target.health > 0) { + if (self.damageMulti == 0) { + self.damageMulti = 1.0; + } + double damage = 5.0 * self.damageMulti; + int newDamage = self.DamageMobj(self, self.target, damage, 'Electric'); + self.target.TraceBleed(newDamage > 0 ? newDamage : damage, self); + } + } +} + +class PWeapVorpalSword_Shock2 : Actor { + int idxTexture; + double lifeTime; + + double damageMulti; + + Actor parent; + + States { + Spawn: + PSK2 A 1 Bright; + Loop; + } + + override void BeginPlay() { + self.lifeTime = 0.5 * 35.0; + } + + override void Tick() { + Super.Tick(); + + self.lifeTime--; + + SwapTexture(); + + self.Scale.x; + self.Scale.y; + } + + void SetParent(Actor nextParent) { + self.parent = nextParent; + } + + void SwapTexture() { + self.idxTexture = (idxTexture + 1) % 2; + self.A_ChangeModel(self.GetClassName(), + modelindex: 0, modelpath: "models/", model: "vorpshk2.md3", + skinindex: 0, skinpath: "models/", String.format("vorpshk2_skin%d", self.idxTexture), + generatorindex: 0 + ); } } \ No newline at end of file