From ef412c20cc27d0a1a4c11e8728c639176e3690b5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 23 Dec 2022 22:16:37 +0100 Subject: [PATCH] - scriptified shootrpg. Due to its ugly special cases this function is most likely not modding-safe. --- source/games/duke/src/player_d.cpp | 171 +----------- source/games/duke/src/player_r.cpp | 140 +--------- wadsrc/static/zscript.txt | 4 + .../games/duke/actors/dukeweapons/rpg.zs | 264 ++++++++++++++++++ .../zscript/games/duke/actors/projectiles.zs | 257 ----------------- .../duke/actors/redneckweapons/boatcannon.zs | 51 ++++ .../duke/actors/redneckweapons/crossbow.zs | 110 ++++++++ wadsrc/static/zscript/games/duke/dukeactor.zs | 1 - 8 files changed, 431 insertions(+), 567 deletions(-) create mode 100644 wadsrc/static/zscript/games/duke/actors/dukeweapons/rpg.zs create mode 100644 wadsrc/static/zscript/games/duke/actors/redneckweapons/boatcannon.zs create mode 100644 wadsrc/static/zscript/games/duke/actors/redneckweapons/crossbow.zs diff --git a/source/games/duke/src/player_d.cpp b/source/games/duke/src/player_d.cpp index eb5b49e4f..4c57c0727 100644 --- a/source/games/duke/src/player_d.cpp +++ b/source/games/duke/src/player_d.cpp @@ -81,166 +81,6 @@ void incur_damage_d(player_struct* p) } -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -static void shootrpg(DDukeActor *actor, int p, DVector3 pos, DAngle ang, int atwith) -{ - auto sect = actor->sector(); - double vel, zvel; - int scount; - - if (actor->spr.extra >= 0) actor->spr.shade = -96; - - scount = 1; - vel = 644 / 16.; - - DDukeActor* aimed = nullptr; - - if (p >= 0) - { - aimed = aim(actor, AUTO_AIM_ANGLE); - if (aimed) - { - auto tex = TexMan.GetGameTexture(aimed->spr.spritetexture()); - double dal = ((aimed->spr.scale.X * tex->GetDisplayHeight()) * 0.5) + 8; - double dist = (ps[p].GetActor()->spr.pos.XY() - aimed->spr.pos.XY()).Length(); - zvel = ((aimed->spr.pos.Z - pos.Z - dal) * vel) / dist; - if (!(aimed->flags2 & SFLAG2_SPECIALAUTOAIM)) - ang = (aimed->spr.pos.XY() - pos.XY()).Angle(); - } - else - setFreeAimVelocity(vel, zvel, ps[p].Angles.getPitchWithView(), 40.5); - } - else - { - double x; - int j = findplayer(actor, &x); - ang = (ps[j].GetActor()->opos.XY() - pos.XY()).Angle(); - if (actor->spr.picnum == DTILE_BOSS3) - { - double zoffs = 32; - if (isWorldTour()) // Twentieth Anniversary World Tour - zoffs *= (actor->spr.scale.Y * 0.8); - pos.Z -= zoffs; - } - else if (actor->spr.picnum == DTILE_BOSS2) - { - vel += 8; - double zoffs = 24; - if (isWorldTour()) // Twentieth Anniversary World Tour - zoffs *= (actor->spr.scale.Y * 0.8); - pos.Z += zoffs; - } - - double dist = (ps[j].GetActor()->spr.pos.XY() - actor->spr.pos.XY()).Length(); - - zvel = ((ps[j].GetActor()->getPrevOffsetZ() - pos.Z) * vel) / dist; - - if (badguy(actor) && (actor->spr.hitag & face_player_smart)) - ang = actor->spr.Angles.Yaw + randomAngle(DAngle22_5 / 4) - DAngle22_5 / 8; - } - if (p < 0) aimed = nullptr; - - auto offset = (ang + DAngle1 * 61.171875).ToVector() * (1024. / 448.); - auto spawned = CreateActor(sect, pos.plusZ(-1) + offset, atwith, 0, DVector2(0.21875, 0.21875), ang, vel, zvel, actor, 4); - - if (!spawned) return; - CallInitialize(spawned); - - if (p >= 0) - { - int snd = spawned->IntVar(NAME_spawnsound); - if (snd > 0) S_PlayActorSound(FSoundID::fromInt(snd), actor); - } - - spawned->spr.extra += (krand() & 7); - if (!(spawned->flags2 & SFLAG2_REFLECTIVE)) - spawned->temp_actor = aimed; - else - { - spawned->spr.yint = gs.numfreezebounces; - spawned->spr.scale *= 0.5; - spawned->vel.Z -= 0.25; - } - - if (p == -1) - { - if (actor->spr.picnum == DTILE_BOSS3) - { - DVector2 spawnofs(ang.Sin() * 4, ang.Cos() * -4); - DAngle aoffs = DAngle22_5 / 32.; - - if ((krand() & 1) != 0) - { - spawnofs = -spawnofs; - aoffs = -aoffs; - } - - if (isWorldTour()) // Twentieth Anniversary World Tour - { - double siz = actor->spr.scale.Y * 0.8; - spawnofs *= siz; - aoffs *= siz; - } - - spawned->spr.pos += spawnofs; - spawned->spr.Angles.Yaw += aoffs; - - spawned->spr.scale = DVector2(0.65625, 0.65625); - } - else if (actor->spr.picnum == DTILE_BOSS2) - { - DVector2 spawnofs(ang.Sin() * (1024. / 56.), ang.Cos() * -(1024. / 56.)); - DAngle aoffs = DAngle22_5 / 16. - DAngle45 + randomAngle(90); - - if (isWorldTour()) { // Twentieth Anniversary World Tour - double siz = actor->spr.scale.Y * 0.9143; - spawnofs *= siz; - aoffs *= siz; - } - - spawned->spr.pos += spawnofs; - spawned->spr.Angles.Yaw += aoffs; - - spawned->spr.scale = DVector2(0.375, 0.375); - } - else if (atwith != DTILE_FREEZEBLAST) - { - spawned->spr.scale = DVector2(0.46875, 0.46875); - spawned->spr.extra >>= 2; - } - } - else if ((isWW2GI() && aplWeaponWorksLike(ps[p].curr_weapon, p) == DEVISTATOR_WEAPON) || (!isWW2GI() && ps[p].curr_weapon == DEVISTATOR_WEAPON)) - { - spawned->spr.extra >>= 2; - spawned->spr.Angles.Yaw += DAngle22_5 / 8 - randomAngle(22.5 / 4); - spawned->vel.Z += 1 - krandf(2); - - if (ps[p].hbomb_hold_delay) - { - DVector2 spawnofs(-ang.Sin()* (1024. / 644.), ang.Cos() * (1024. / 644.)); - spawned->spr.pos += spawnofs; - } - else - { - DVector2 spawnofs(ang.Sin()* 4, ang.Cos() * -4); - spawned->spr.pos += spawnofs; - } - spawned->spr.scale *= 0.5; - } - - spawned->spr.cstat = CSTAT_SPRITE_YCENTER; - if (atwith == DTILE_RPG) - spawned->clipdist = 1; - else - spawned->clipdist = 10; - -} - //--------------------------------------------------------------------------- // // @@ -283,16 +123,7 @@ void shoot_d(DDukeActor* actor, int atwith, PClass *cls) if (cls == nullptr) cls = GetSpawnType(atwith); - if (cls && cls->IsDescendantOf(RUNTIME_CLASS(DDukeActor)) && CallShootThis(static_cast(GetDefaultByType(cls)), actor, p, spos, sang)) return; - if (cls && atwith == -1) atwith = GetDefaultByType(cls)->spr.picnum; - - switch (atwith) - { - case DTILE_RPG: - shootrpg(actor, p, spos, sang, atwith); - break; - } - return; + CallShootThis(static_cast(GetDefaultByType(cls)), actor, p, spos, sang); } //--------------------------------------------------------------------------- diff --git a/source/games/duke/src/player_r.cpp b/source/games/duke/src/player_r.cpp index 01c4e83f9..70f7830f3 100644 --- a/source/games/duke/src/player_r.cpp +++ b/source/games/duke/src/player_r.cpp @@ -83,128 +83,6 @@ void incur_damage_r(player_struct* p) // //--------------------------------------------------------------------------- -static void shootrpg(DDukeActor* actor, int p, DVector3 pos, DAngle ang, int atwith) -{ - auto sect = actor->sector(); - double vel, zvel; - int scount; - - DDukeActor* act90 = nullptr; - if (actor->spr.extra >= 0) actor->spr.shade = -96; - - scount = 1; - vel = 40.25; - - DDukeActor* aimed = nullptr; - - if (p >= 0) - { - aimed = aim(actor, AUTO_AIM_ANGLE); - if (aimed) - { - if (isRRRA() && atwith == RTILE_RPG2) - { - if (aimed->IsKindOf(NAME_RedneckHen)) - act90 = ps[screenpeek].GetActor(); - else - act90 = aimed; - } - auto tex = TexMan.GetGameTexture(aimed->spr.spritetexture()); - double dal = ((aimed->spr.scale.X * tex->GetDisplayHeight()) * 0.5) + 8; - double dist = (ps[p].GetActor()->spr.pos.XY() - aimed->spr.pos.XY()).Length(); - zvel = ((aimed->spr.pos.Z - pos.Z - dal) * vel) / dist; - if (!(aimed->flags2 & SFLAG2_SPECIALAUTOAIM)) - ang = (aimed->spr.pos.XY() - pos.XY()).Angle(); - } - else - setFreeAimVelocity(vel, zvel, ps[p].Angles.getPitchWithView(), 40.5); - - } - else - { - double x; - int j = findplayer(actor, &x); - ang = (ps[j].GetActor()->opos.XY() - pos.XY()).Angle(); - - double dist = (ps[j].GetActor()->spr.pos.XY() - actor->spr.pos.XY()).Length(); - zvel = ((ps[j].GetActor()->getPrevOffsetZ() - pos.Z) * vel) / dist; - - if (badguy(actor) && (actor->spr.hitag & face_player_smart)) - ang = actor->spr.Angles.Yaw + randomAngle(22.5 / 4) - DAngle22_5 / 8; - } - - if (p < 0) aimed = nullptr; - - auto offset = (ang + DAngle1 * 61).ToVector() * (1024 / 448.); - auto spawned = CreateActor(sect, pos.plusZ(-1) + offset, atwith, 0, DVector2(0.21875, 0.21875), ang, vel, zvel, actor, 4); - - if (!spawned) return; - CallInitialize(spawned); - - if (p >= 0) - { - int snd = spawned->IntVar(NAME_spawnsound); - if (snd > 0) S_PlayActorSound(FSoundID::fromInt(snd), actor); - } - - spawned->seek_actor = act90; - - spawned->spr.extra += (krand() & 7); - if (!(spawned->flags2 & SFLAG2_REFLECTIVE)) - spawned->temp_actor = aimed; - else - { - spawned->spr.yint = gs.numfreezebounces; - spawned->spr.scale *= 0.5; - spawned->vel.Z -= 0.125; - } - - if (p == -1) - { - if (actor->spr.picnum == RTILE_HULK) - { - spawned->spr.scale = DVector2(0.125, 0.125); - } - else if (atwith != RTILE_FREEZEBLAST) - { - spawned->spr.scale = DVector2(0.46875, 0.46875); - spawned->spr.extra >>= 2; - } - } - else if (ps[p].curr_weapon == TIT_WEAPON) - { - spawned->spr.extra >>= 2; - spawned->spr.Angles.Yaw += DAngle22_5 / 8 - randomAngle(DAngle22_5 / 4); - spawned->vel.Z += 1 - krandf(2); - - if (ps[p].hbomb_hold_delay) - { - DVector2 spawnofs(ang.Sin() * (1024. / 644.), ang.Cos() * -(1024. / 644.)); - spawned->spr.pos += spawnofs; - } - else - { - DVector2 spawnofs(ang.Sin() * 4, ang.Cos() * -4); - spawned->spr.pos += spawnofs; - } - spawned->spr.scale *= 0.5; - } - - spawned->spr.cstat = CSTAT_SPRITE_YCENTER; - if (atwith == RTILE_RPG || (atwith == RTILE_RPG2 && isRRRA())) - spawned->clipdist = 1; - else - spawned->clipdist = 10; - - -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - void shoot_r(DDukeActor* actor, int atwith, PClass* cls) { int p; @@ -237,23 +115,7 @@ void shoot_r(DDukeActor* actor, int atwith, PClass* cls) if (cls == nullptr) cls = GetSpawnType(atwith); - if (cls && cls->IsDescendantOf(RUNTIME_CLASS(DDukeActor)) && CallShootThis(static_cast(GetDefaultByType(cls)), actor, p, spos, sang)) return; - if (cls && atwith == -1) atwith = GetDefaultByType(cls)->spr.picnum; - - switch (atwith) - { - case RTILE_RPG2: - case RTILE_BOATGRENADE: - if (isRRRA()) goto rrra_rpg2; - else break; - - case RTILE_RPG: - case RTILE_SAWBLADE: - rrra_rpg2: - shootrpg(actor, p, spos, sang, atwith); - break; - } - return; + CallShootThis(static_cast(GetDefaultByType(cls)), actor, p, spos, sang); } //--------------------------------------------------------------------------- diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 0768935e2..870703f2a 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -165,6 +165,10 @@ version "4.10" #include "zscript/games/duke/actors/dukeweapons/grower.zs" #include "zscript/games/duke/actors/dukeweapons/tripbomb.zs" #include "zscript/games/duke/actors/dukeweapons/freezer.zs" +#include "zscript/games/duke/actors/dukeweapons/rpg.zs" + +#include "zscript/games/duke/actors/redneckweapons/crossbow.zs" +#include "zscript/games/duke/actors/redneckweapons/boatcannon.zs" #include "zscript/games/duke/actors/redneckenemies/vixen.zs" diff --git a/wadsrc/static/zscript/games/duke/actors/dukeweapons/rpg.zs b/wadsrc/static/zscript/games/duke/actors/dukeweapons/rpg.zs new file mode 100644 index 000000000..138e0be75 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/dukeweapons/rpg.zs @@ -0,0 +1,264 @@ +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class DukeRPG : DukeProjectile +{ + default + { + pic "RPG"; + +FULLBRIGHT; + +INFLAME; + +UNDERWATERSLOWDOWN; + +ALWAYSROTATE2; + +EXPLOSIVE; + +DOUBLEDMGTHRUST; + +NOFLOORPAL; + +BREAKMIRRORS; + DukeProjectile.SpawnSound "RPG_SHOOT"; + } + + override bool premoveeffect() + { + if ((!self.ownerActor || !self.ownerActor.bNONSMOKYROCKET) && self.scale.X >= 0.15625 && self.sector.lotag != ST_2_UNDERWATER) + { + let spawned = self.spawn("DukeSmallSmoke"); + if (spawned) spawned.pos.Z += 1; + } + return super.premoveeffect(); + } + + override bool postmoveeffect(CollisionData coll) + { + Super.postmoveeffect(coll); + if (self.temp_actor != nullptr && (self.pos.XY - self.temp_actor.pos.XY).LengthSquared() < 16 * 16) + coll.setActor(self.temp_actor); + return false; + } + + override void posthiteffect(CollisionData coll) + { + self.rpgexplode(coll.type, oldpos, true, -1, "RPG_EXPLODE"); + self.Destroy(); + } + + void rpgexplode(int hit, Vector3 pos, bool exbottom, int newextra, Sound playsound) + { + let explosion = self.spawn("DukeExplosion2"); + if (!explosion) return; + explosion.pos = pos; + + if (self.scale.X < 0.15625) + { + explosion.scale = (0.09375, 0.09375); + } + else if (hit == kHitSector) + { + if (self.vel.Z > 0 && exbottom) + self.spawn("DukeExplosion2Bot"); + else + { + explosion.cstat |= CSTAT_SPRITE_YFLIP; + explosion.pos.Z += 48; + } + } + if (newextra > 0) self.extra = newextra; + self.PlayActorSound(playsound); + + if (self.scale.X >= 0.15625) + { + int x = self.extra; + self.hitradius(gs.rpgblastradius, x >> 2, x >> 1, x - (x >> 2), x); + } + else + { + int x = self.extra + (Duke.global_random() & 3); + self.hitradius((gs.rpgblastradius >> 1), x >> 2, x >> 1, x - (x >> 2), x); + } + } + + override void Tick() + { + super.Tick(); + if (self.sector && self.sector.lotag == ST_2_UNDERWATER && self.scale.X >= 0.15625 && Duke.rnd(140)) + self.spawn('DukeWaterBubble'); + + } + override class GetRadiusDamageType(int targhealth) + { + if (targhealth > 0) return 'DukeRPG'; + return 'DukeRadiusExplosion'; + } + + + //--------------------------------------------------------------------------- + // + // this is very, very messy. There's really no point trying to make this + // moddable - that will require new shooting functions with better setup. + // + //--------------------------------------------------------------------------- + + override bool ShootThis(DukeActor actor, DukePlayer p, Vector3 pos, double ang) const + { + let sect = actor.sector; + double vel, zvel; + int scount; + + DukeActor act90 = nullptr; + if (actor.extra >= 0) actor.shade = -96; + + scount = 1; + vel = 40.25; + + DukeActor aimed = nullptr; + + if (p != null) + { + aimed = actor.aim(self); + if (aimed) + { + if (self.GetClass() is 'RedneckChickenArrow') + { + if (aimed is 'RedneckHen') + act90 = p.actor; + else + act90 = aimed; + } + double dal = ((aimed.scale.X * aimed.spriteHeight()) * 0.5) + 8; + double dist = (p.actor.pos.XY - aimed.pos.XY).Length(); + zvel = ((aimed.pos.Z - pos.Z - dal) * vel) / dist; + if (!(aimed.bSPECIALAUTOAIM)) + ang = (aimed.pos.XY - pos.XY).Angle(); + } + else + [vel, zvel] = Raze.setFreeAimVelocity(vel, zvel, p.getPitchWithView(), 40.5); + } + else + { + let j = actor.findplayer(); + ang = (j.actor.opos.XY - pos.XY).Angle(); + if (actor is 'DukeBoss3') + { + double zoffs = 32; + if (Raze.isWorldTour()) // Twentieth Anniversary World Tour + zoffs *= (actor.scale.Y * 0.8); + pos.Z -= zoffs; + } + else if (actor is 'DukeBoss2') + { + vel += 8; + double zoffs = 24; + if (Raze.isWorldTour()) // Twentieth Anniversary World Tour + zoffs *= (actor.scale.Y * 0.8); + pos.Z += zoffs; + } + + double dist = (j.actor.pos.XY - actor.pos.XY).Length(); + + zvel = ((j.actor.opos.Z + j.actor.viewzoffset - pos.Z) * vel) / dist; + + if (actor.bBADGUY && (actor.hitag & face_player_smart)) + ang = actor.Angle + frandom(-22.5 / 8, 22.5 / 8); + aimed = nullptr; + } + + + let offset = (ang + 61.171875).ToVector() * (1024. / 448.); + let spawned = dlevel.SpawnActor(sect, pos.plusZ(-1) + offset, self.GetClass(), 0, (0.21875, 0.21875), ang, vel, zvel, actor, STAT_PROJECTILE); + + if (!spawned) return true; + + if (p != null) + { + let snd = self.spawnsound; + if (snd > 0) spawned.PlayActorSound(snd); + } + + spawned.seek_actor = act90; + spawned.extra += random(0, 7); + spawned.temp_actor = aimed; + + if (p == null) + { + // Setup shit is RPG only + if (actor is 'RedneckHulk') + { + spawned.scale = (0.125, 0.125); + } + else if (actor is 'DukeBoss3') + { + Vector2 spawnofs = (sin(ang) * 4, cos(ang) * -4); + let aoffs = 22.5 / 32.; + + if (random(0, 1)) + { + spawnofs = -spawnofs; + aoffs = -aoffs; + } + + if (Raze.isWorldTour()) // Twentieth Anniversary World Tour + { + double siz = actor.scale.Y * 0.8; + spawnofs *= siz; + aoffs *= siz; + } + + spawned.pos += spawnofs; + spawned.Angle += aoffs; + + spawned.scale = (0.65625, 0.65625); + } + else if (actor is 'DukeBoss2') + { + Vector2 spawnofs = (sin(ang) * (1024. / 56.), cos(ang) * -(1024. / 56.)); + let aoffs = 22.5 / 16. - frandom(-45, 45); + + if (Raze.isWorldTour()) // Twentieth Anniversary World Tour + { + double siz = actor.scale.Y * 0.9143; + spawnofs *= siz; + aoffs *= siz; + } + + spawned.pos += spawnofs; + spawned.Angle += aoffs; + + spawned.scale = (0.375, 0.375); + } + else + { + spawned.scale = (0.46875, 0.46875); + spawned.extra >>= 2; + } + } + else if (p.curr_weapon == DukeWpn.DEVISTATOR_WEAPON) + { + spawned.extra >>= 2; + spawned.Angle += frandom(-22.5 / 8, 22.5 / 8); + spawned.vel.Z += frandom(-1, 1); + + if (p.hbomb_hold_delay) + { + Vector2 spawnofs = (sin(ang) * -(1024. / 644.), cos(ang) * (1024. / 644.)); + spawned.pos += spawnofs; + } + else + { + Vector2 spawnofs = (sin(ang) * 4, cos(ang) * -4); + spawned.pos += spawnofs; + } + spawned.scale *= 0.5; + } + + spawned.cstat = CSTAT_SPRITE_YCENTER; + spawned.clipdist = 1; + return true; + } + + +} + + + diff --git a/wadsrc/static/zscript/games/duke/actors/projectiles.zs b/wadsrc/static/zscript/games/duke/actors/projectiles.zs index e0919f5bc..28ee63066 100644 --- a/wadsrc/static/zscript/games/duke/actors/projectiles.zs +++ b/wadsrc/static/zscript/games/duke/actors/projectiles.zs @@ -285,103 +285,6 @@ class RedneckFirelaser : DukeFirelaser } -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -class DukeRPG : DukeProjectile -{ - default - { - pic "RPG"; - +FULLBRIGHT; - +INFLAME; - +UNDERWATERSLOWDOWN; - +ALWAYSROTATE2; - +EXPLOSIVE; - +DOUBLEDMGTHRUST; - +NOFLOORPAL; - +BREAKMIRRORS; - DukeProjectile.SpawnSound "RPG_SHOOT"; - } - - override bool premoveeffect() - { - if ((!self.ownerActor || !self.ownerActor.bNONSMOKYROCKET) && self.scale.X >= 0.15625 && self.sector.lotag != ST_2_UNDERWATER) - { - let spawned = self.spawn("DukeSmallSmoke"); - if (spawned) spawned.pos.Z += 1; - } - return super.premoveeffect(); - } - - override bool postmoveeffect(CollisionData coll) - { - Super.postmoveeffect(coll); - if (self.temp_actor != nullptr && (self.pos.XY - self.temp_actor.pos.XY).LengthSquared() < 16 * 16) - coll.setActor(self.temp_actor); - return false; - } - - override void posthiteffect(CollisionData coll) - { - self.rpgexplode(coll.type, oldpos, true, -1, "RPG_EXPLODE"); - self.Destroy(); - } - - void rpgexplode(int hit, Vector3 pos, bool exbottom, int newextra, Sound playsound) - { - let explosion = self.spawn("DukeExplosion2"); - if (!explosion) return; - explosion.pos = pos; - - if (self.scale.X < 0.15625) - { - explosion.scale = (0.09375, 0.09375); - } - else if (hit == kHitSector) - { - if (self.vel.Z > 0 && exbottom) - self.spawn("DukeExplosion2Bot"); - else - { - explosion.cstat |= CSTAT_SPRITE_YFLIP; - explosion.pos.Z += 48; - } - } - if (newextra > 0) self.extra = newextra; - self.PlayActorSound(playsound); - - if (self.scale.X >= 0.15625) - { - int x = self.extra; - self.hitradius(gs.rpgblastradius, x >> 2, x >> 1, x - (x >> 2), x); - } - else - { - int x = self.extra + (Duke.global_random() & 3); - self.hitradius((gs.rpgblastradius >> 1), x >> 2, x >> 1, x - (x >> 2), x); - } - } - - override void Tick() - { - super.Tick(); - if (self.sector && self.sector.lotag == ST_2_UNDERWATER && self.scale.X >= 0.15625 && Duke.rnd(140)) - self.spawn('DukeWaterBubble'); - - } - override class GetRadiusDamageType(int targhealth) - { - if (targhealth > 0) return 'DukeRPG'; - return 'DukeRadiusExplosion'; - } - -} - - //--------------------------------------------------------------------------- // // @@ -716,166 +619,6 @@ class DukeFireball : DukeProjectile // WorldTour only } } -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -class RedneckDynamiteArrow : DukeRPG -{ - default - { - pic "RPG"; - } - - override bool weaponhitsprite_pre(DukeActor targ) - { - if (targ.bTRANSFERPALTOJIBS && targ.pal == 19) - { - self.PlayActorSound("RPG_EXPLODE"); - let spawned = self.spawn("DukeExplosion2"); - if (spawned) - spawned.pos = oldpos; - return true; - } - return Super.weaponhitsprite_pre(targ); - } - - override void posthiteffect(CollisionData coll) - { - self.rpgexplode(coll.type, oldpos, false, -1, "RPG_EXPLODE"); - self.Destroy(); - } - - -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -class RedneckChickenArrow : RedneckDynamiteArrow -{ - default - { - pic "RPG2"; - +FORCEAUTOAIM; - +NOFLOORPAL; - +ALWAYSROTATE2; - DukeProjectile.SpawnSound "CHICKENBOW_FIRE"; - } - - override void Initialize() - { - self.hitag = 0; - self.lotsofstuff("RedneckFeather", random(1, 4)); - } - - override bool premoveeffect() - { - // seeker handling - self.hitag++; - if (self.scale.X >= 0.15625 && self.sector.lotag != ST_2_UNDERWATER) - { - let spawned = self.spawn("DukeSmallSmoke"); - if (spawned) spawned.pos.Z += 1; - if (random(0, 15) == 2) - { - self.spawn("RedneckFeather"); - } - } - DukeActor ts = self.seek_actor; - if (!ts) return false; - - if (ts.extra <= 0) - self.seek_actor = null; - - if (self.seek_actor && self.hitag > 5) - { - let ang = (ts.pos - self.pos).Angle(); - let ang2 = deltaangle(ang, self.angle); - // this was quite broken in the original code. Fixed so that it seeks properly - if (abs(ang2) < 17.5) - { - self.angle = ang; - } - else if (ang2 > 0) - { - self.angle -= 9; - } - else - self.angle += 9; - - if (self.hitag > 180) - if (self.vel.Z <= 0) - self.vel.Z += 200 / 256; - } - return false; - } - - override void posthiteffect(CollisionData coll) - { - self.rpgexplode(coll.type, oldpos, false, 150, "CHKBOWEX"); - self.Destroy(); - } - - -} - -//--------------------------------------------------------------------------- -// -// -// -//--------------------------------------------------------------------------- - -class RedneckBoatGrenade : RedneckDynamiteArrow // RRRA only -{ - default - { - pic "BOATGRENADE"; - -DOUBLEDMGTHRUST; - -ALWAYSROTATE2; - DukeProjectile.SpawnSound "MORTAR"; - } - - override void Initialize() - { - - self.extra = 10; - self.vel.Z = -10; - self.vel.X *= 2; - super.Initialize(); - } - - override bool premoveeffect() - { - if (self.extra) - { - self.vel.Z = -(self.extra * 250/256.); // 250 looks like a typo... - self.extra--; - } - else - self.makeitfall(); - - return Super.premoveeffect(); - } - - override void posthiteffect(CollisionData coll) - { - self.rpgexplode(coll.type, oldpos, false, 160, "RPG_EXPLODE"); - self.Destroy(); - } - - override class GetRadiusDamageType(int targhealth) - { - return 'DukeRadiusExplosion'; - } - -} - //--------------------------------------------------------------------------- // // this class is called shitball - but it's not just about throwing shit in the game, diff --git a/wadsrc/static/zscript/games/duke/actors/redneckweapons/boatcannon.zs b/wadsrc/static/zscript/games/duke/actors/redneckweapons/boatcannon.zs new file mode 100644 index 000000000..c6bd3f554 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/redneckweapons/boatcannon.zs @@ -0,0 +1,51 @@ +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class RedneckBoatGrenade : RedneckDynamiteArrow // RRRA only +{ + default + { + pic "BOATGRENADE"; + -DOUBLEDMGTHRUST; + -ALWAYSROTATE2; + DukeProjectile.SpawnSound "MORTAR"; + } + + override void Initialize() + { + + self.extra = 10; + self.vel.Z = -10; + self.vel.X *= 2; + super.Initialize(); + } + + override bool premoveeffect() + { + if (self.extra) + { + self.vel.Z = -(self.extra * 250/256.); // 250 looks like a typo... + self.extra--; + } + else + self.makeitfall(); + + return Super.premoveeffect(); + } + + override void posthiteffect(CollisionData coll) + { + self.rpgexplode(coll.type, oldpos, false, 160, "RPG_EXPLODE"); + self.Destroy(); + } + + override class GetRadiusDamageType(int targhealth) + { + return 'DukeRadiusExplosion'; + } + +} + diff --git a/wadsrc/static/zscript/games/duke/actors/redneckweapons/crossbow.zs b/wadsrc/static/zscript/games/duke/actors/redneckweapons/crossbow.zs new file mode 100644 index 000000000..16bc12ea3 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/actors/redneckweapons/crossbow.zs @@ -0,0 +1,110 @@ + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class RedneckDynamiteArrow : DukeRPG +{ + default + { + pic "RPG"; + } + + override bool weaponhitsprite_pre(DukeActor targ) + { + if (targ.bTRANSFERPALTOJIBS && targ.pal == 19) + { + self.PlayActorSound("RPG_EXPLODE"); + let spawned = self.spawn("DukeExplosion2"); + if (spawned) + spawned.pos = oldpos; + return true; + } + return Super.weaponhitsprite_pre(targ); + } + + override void posthiteffect(CollisionData coll) + { + self.rpgexplode(coll.type, oldpos, false, -1, "RPG_EXPLODE"); + self.Destroy(); + } + + +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class RedneckChickenArrow : RedneckDynamiteArrow +{ + default + { + pic "RPG2"; + +FORCEAUTOAIM; + +NOFLOORPAL; + +ALWAYSROTATE2; + DukeProjectile.SpawnSound "CHICKENBOW_FIRE"; + } + + override void Initialize() + { + self.hitag = 0; + self.lotsofstuff("RedneckFeather", random(1, 4)); + } + + override bool premoveeffect() + { + // seeker handling + self.hitag++; + if (self.scale.X >= 0.15625 && self.sector.lotag != ST_2_UNDERWATER) + { + let spawned = self.spawn("DukeSmallSmoke"); + if (spawned) spawned.pos.Z += 1; + if (random(0, 15) == 2) + { + self.spawn("RedneckFeather"); + } + } + DukeActor ts = self.seek_actor; + if (!ts) return false; + + if (ts.extra <= 0) + self.seek_actor = null; + + if (self.seek_actor && self.hitag > 5) + { + let ang = (ts.pos - self.pos).Angle(); + let ang2 = deltaangle(ang, self.angle); + // this was quite broken in the original code. Fixed so that it seeks properly + if (abs(ang2) < 17.5) + { + self.angle = ang; + } + else if (ang2 > 0) + { + self.angle -= 9; + } + else + self.angle += 9; + + if (self.hitag > 180) + if (self.vel.Z <= 0) + self.vel.Z += 200 / 256; + } + return false; + } + + override void posthiteffect(CollisionData coll) + { + self.rpgexplode(coll.type, oldpos, false, 150, "CHKBOWEX"); + self.Destroy(); + } + + +} + diff --git a/wadsrc/static/zscript/games/duke/dukeactor.zs b/wadsrc/static/zscript/games/duke/dukeactor.zs index c8eb1bd16..80cae31e2 100644 --- a/wadsrc/static/zscript/games/duke/dukeactor.zs +++ b/wadsrc/static/zscript/games/duke/dukeactor.zs @@ -338,7 +338,6 @@ class DukeActor : CoreActor native } return true; } - } extend struct _