diff --git a/language.version b/language.version index 8371ec493..7c5e3b47a 100644 --- a/language.version +++ b/language.version @@ -1,2 +1,2 @@ [default] -SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.2b r551 \cu(Sat 19 Sep 17:45:52 CEST 2020)"; +SWWM_MODVER="\chSWWM \czGZ\c- \cw0.9.3b r553 \cu(Sun 20 Sep 15:05:43 CEST 2020)"; diff --git a/modeldef.eviscerator b/modeldef.eviscerator index 2d61b494d..fecf13de2 100644 --- a/modeldef.eviscerator +++ b/modeldef.eviscerator @@ -16,6 +16,36 @@ Model "EvisceratorCasing" FrameIndex XZW1 C 0 0 } +Model "EvisceratorChunk" +{ + Path "models" + + Model 0 "Chunky_d.3d" + Skin 0 "Chunky.png" + Scale 0.02 0.02 0.02 + USEACTORPITCH + USEACTORROLL + + FrameIndex XZW1 A 0 0 + FrameIndex XZW1 B 0 1 + FrameIndex XZW1 C 0 2 + FrameIndex XZW1 D 0 3 + FrameIndex XZW1 E 0 4 + FrameIndex XZW1 F 0 5 + FrameIndex XZW1 G 0 6 + FrameIndex XZW1 H 0 7 + ZOffset 0.2 + FrameIndex XZW2 A 0 0 + FrameIndex XZW2 B 0 1 + FrameIndex XZW2 C 0 2 + FrameIndex XZW2 D 0 3 + FrameIndex XZW2 E 0 4 + FrameIndex XZW2 F 0 5 + FrameIndex XZW2 G 0 6 + FrameIndex XZW2 H 0 7 +} + + Model "EvisceratorProj" { Path "models" diff --git a/modeldef.hellblazer b/modeldef.hellblazer index f6f8597fd..ad9cb00c1 100644 --- a/modeldef.hellblazer +++ b/modeldef.hellblazer @@ -50,7 +50,7 @@ Model "HellblazerClusterMini" Model 0 "HellblazerProj_d.3d" Skin 0 "HellblazerMissile_Cluster.png" - Scale 0.02 0.02 0.02 + Scale 0.05 0.05 0.05 USEACTORPITCH USEACTORROLL diff --git a/modeldef.misc b/modeldef.misc index dee2dde70..6aadafa9d 100644 --- a/modeldef.misc +++ b/modeldef.misc @@ -28,6 +28,35 @@ Model "FancyConfetti" FrameIndex XZW1 J 0 0 } +Model "SWWMChip" +{ + Path "models" + + Model 0 "Chunky_d.3d" + Skin 0 "Chunky.png" + Scale 0.02 0.02 0.02 + USEACTORPITCH + USEACTORROLL + + FrameIndex XZW1 A 0 0 + FrameIndex XZW1 B 0 1 + FrameIndex XZW1 C 0 2 + FrameIndex XZW1 D 0 3 + FrameIndex XZW1 E 0 4 + FrameIndex XZW1 F 0 5 + FrameIndex XZW1 G 0 6 + FrameIndex XZW1 H 0 7 + ZOffset 0.2 + FrameIndex XZW2 A 0 0 + FrameIndex XZW2 B 0 1 + FrameIndex XZW2 C 0 2 + FrameIndex XZW2 D 0 3 + FrameIndex XZW2 E 0 4 + FrameIndex XZW2 F 0 5 + FrameIndex XZW2 G 0 6 + FrameIndex XZW2 H 0 7 +} + Model "ReflectedBullet" { Path "models" diff --git a/models/Chunky.png b/models/Chunky.png new file mode 100644 index 000000000..2e5ffb7cc Binary files /dev/null and b/models/Chunky.png differ diff --git a/models/Chunky_a.3d b/models/Chunky_a.3d new file mode 100644 index 000000000..2778d8af2 Binary files /dev/null and b/models/Chunky_a.3d differ diff --git a/models/Chunky_d.3d b/models/Chunky_d.3d new file mode 100644 index 000000000..924ec6a35 Binary files /dev/null and b/models/Chunky_d.3d differ diff --git a/sprites/ETRLA0.png b/sprites/ETRLA0.png new file mode 100644 index 000000000..51b11ecc7 Binary files /dev/null and b/sprites/ETRLA0.png differ diff --git a/zscript/swwm_common.zsc b/zscript/swwm_common.zsc index d6f17a926..d74eecc1d 100644 --- a/zscript/swwm_common.zsc +++ b/zscript/swwm_common.zsc @@ -39,7 +39,7 @@ Class PaletteLight : DynamicLight } private void UpdateLight() { - int index = 255-((255*ReactionTime)/abs(default.ReactionTime)); + int index = clamp(255-((255*ReactionTime)/abs(default.ReactionTime)),0,255); args[LIGHT_RED] = pal[index].r; args[LIGHT_GREEN] = pal[index].g; args[LIGHT_BLUE] = pal[index].b; @@ -622,7 +622,7 @@ Class SWWMChip : Actor { SWWMChip prevchip, nextchip; bool killme; - double rollvel; + double anglevel, pitchvel, rollvel; bool dead; Sector tracksector; int trackplane; @@ -645,8 +645,10 @@ Class SWWMChip : Actor } override void PostBeginPlay() { + anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); + pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); - frame = Random[Junk](0,5); + frame = Random[Junk](0,7); scale *= Frandom[Junk](0.8,1.2); SWWMHandler.QueueChip(self); } @@ -768,6 +770,8 @@ Class SWWMChip : Actor trackplane = 0; } vel = (0,0,0); + pitch = 0; + roll = 0; dead = true; SetStateLabel("Death"); return; @@ -790,22 +794,23 @@ Class SWWMChip : Actor States { Spawn: - JUNK # 1 + XZW1 # 1 { + angle += anglevel; + pitch += pitchvel; roll += rollvel; } Loop; Bounce: - JUNK # 0 + XZW1 # 0 { + anglevel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); + pitchvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); rollvel = FRandom[Junk](10,30)*RandomPick[Junk](-1,1); } Goto Spawn; Death: - JUNK # -1; - Stop; - Dummy: - JUNK ABCDEF -1; + XZW2 # -1; Stop; } } diff --git a/zscript/swwm_danmaku.zsc b/zscript/swwm_danmaku.zsc index cbe406b65..f30b7266a 100644 --- a/zscript/swwm_danmaku.zsc +++ b/zscript/swwm_danmaku.zsc @@ -1,12 +1,11 @@ // Mr. BIG SHOT Industries "Eviscerator" High Load Flak Cannon (from SWWM series) // Slot 5, replaces Chaingun, Dragon Claw, Hammer of Retribution -Class EvisceratorChunkLight : DynamicLight +Class EvisceratorChunkLight : PointLightAttenuated { Default { - DynamicLight.Type "Point"; - Args 255,224,128,8; + Args 255,224,128,16; } override void Tick() { @@ -18,7 +17,7 @@ Class EvisceratorChunkLight : DynamicLight } SetOrigin(target.pos,true); if ( isFrozen() ) return; - double intst = clamp((7-EvisceratorChunk(target).lifetime*10)/7.,0,1); + double intst = clamp((.7-EvisceratorChunk(target).lifetime)/.7,0.,1.); args[LIGHT_RED] = int(255*intst); args[LIGHT_GREEN] = int(224*intst); args[LIGHT_BLUE] = int(128*intst); @@ -70,10 +69,45 @@ Class ChunkImpact : Actor } } +Class EvisceratorChunkGlow : Actor +{ + Default + { + RenderStyle "Add"; + Radius .1; + Height 0.; + Scale .25; + +FORCEXYBILLBOARD; + +NOGRAVITY; + +NOBLOCKMAP; + +NOINTERACTION; + +DONTSPLASH; + +NOTELEPORT; + } + override void Tick() + { + if ( isFrozen() ) return; + if ( !EvisceratorChunk(target) ) + { + Destroy(); + return; + } + SetOrigin(target.pos,true); + alpha = clamp((.7-EvisceratorChunk(target).lifetime)/.7,0.,1.); + if ( alpha <= 0. ) Destroy(); + } + States + { + Spawn: + ETRL A -1 Bright; + Stop; + } +} + Class EvisceratorChunk : Actor { Actor lasthit; - double rollvel; + double anglevel, pitchvel, rollvel; double lifetime, lifespeed; Vector3 oldvel; bool justdied; @@ -108,11 +142,15 @@ Class EvisceratorChunk : Actor Super.PostBeginPlay(); let l = Spawn("EvisceratorChunkLight",pos); l.target = self; + let t = Spawn("EvisceratorChunkGlow",pos); + t.target = self; lifetime = 0; lifespeed = FRandom[Eviscerator](0.01,0.02); + anglevel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1); + pitchvel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1); rollvel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1); scale *= Frandom[Eviscerator](0.8,1.2); - frame = Random[Eviscerator](0,5); + frame = Random[Eviscerator](0,7); } override void Tick() @@ -131,6 +169,7 @@ Class EvisceratorChunk : Actor // I guess I can blame graf, randi, or whoever else if ( isFrozen() || justdied ) return; lifetime += lifespeed; + if ( waterlevel > 0 ) lifetime = max(.7,lifetime); A_SetTranslation(tls[clamp(int(lifetime*10),0,7)]); if ( !Random[Eviscerator](0,3) && (lifetime < .7) ) { @@ -140,7 +179,11 @@ Class EvisceratorChunk : Actor s.alpha *= scale.x*max(0,.7-lifetime)*1.5; } if ( !InStateSequence(CurState,FindState("Death")) ) + { + angle += anglevel; + pitch += pitchvel; roll += rollvel; + } } void A_HandleBounce() @@ -200,6 +243,8 @@ Class EvisceratorChunk : Actor } A_Gravity(); gravity = .35; + anglevel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1)*(vel.length()/speed); + pitchvel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1)*(vel.length()/speed); rollvel = FRandom[Eviscerator](50,100)*RandomPick[Eviscerator](-1,1)*(vel.length()/speed); A_StartSound("eviscerator/hit",CHAN_WEAPON,CHANF_OVERLAP,.4); if ( swwm_extraalert ) A_AlertMonsters(300); @@ -270,18 +315,20 @@ Class EvisceratorChunk : Actor States { Spawn: - JUNK # -1; + XZW1 # -1; Stop; Bounce: - JUNK # 0 A_HandleBounce(); + XZW1 # 0 A_HandleBounce(); Goto Spawn; Death: - JUNK # 0 + XZW2 # 0 { + pitch = 0; + roll = 0; bMOVEWITHSECTOR = true; A_SetTics(Random[Eviscerator](30,50)); } - JUNK # 1 A_FadeOut(); + XZW2 # 1 A_FadeOut(); Wait; XDeath: TNT1 A 35 { invoker.justdied = true; } diff --git a/zscript/swwm_deathlydeathcannon.zsc b/zscript/swwm_deathlydeathcannon.zsc index 5ffcc6891..982bcb2bd 100644 --- a/zscript/swwm_deathlydeathcannon.zsc +++ b/zscript/swwm_deathlydeathcannon.zsc @@ -1214,7 +1214,7 @@ Class GatherDust : Actor if ( distto < (32.*target.scale.x) ) { // sucked in - target.specialf2 += FRandom[ExploS](.1,.4); + target.specialf2 += FRandom[ExploS](.2,2.); Destroy(); return; } @@ -1959,6 +1959,92 @@ Class YnykronVoidSparkle : Actor Stop; } } +Class YnykronSingularityExplosionArm : Actor +{ + Default + { + PROJECTILE; + +THRUACTORS; + +BOUNCEONWALLS; + +BOUNCEONFLOORS; + +BOUNCEONCEILINGS; + +NODAMAGETHRUST; + +FORCERADIUSDMG; + -NOGRAVITY; + Gravity 0.35; + BounceFactor 1.0; + Radius 4; + Height 4; + } + override void PostBeginPlay() + { + Super.PostBeginPlay(); + reactiontime = Random[ExploS](10,20); + double ang, pt; + ang = FRandom[ExploS](0,360); + pt = FRandom[ExploS](-90,90); + vel = (cos(ang)*cos(pt),sin(ang)*cos(pt),-sin(pt))*FRandom[ExploS](20.,40.); + } + States + { + Spawn: + TNT1 A 1 + { + A_CountDown(); + if ( !(reactiontime%2) ) + { + Spawn("YnykronSingularityExplosionTrail",pos); + Vector3 pvel = (FRandom[ExploS](-1,1),FRandom[ExploS](-1,1),FRandom[ExploS](-1,1)).unit()*FRandom[ExploS](1,5); + let s = Spawn("SWWMHalfSmoke",pos); + s.SetShade(Color(1,1,1)*Random[ExploS](128,160)+Color(28,0,31)); + s.A_SetRenderStyle(s.alpha*(.1+.4*(ReactionTime/15.)),STYLE_AddShaded); + s.vel = pvel+vel*.2; + s.special1 = Random[ExploS](1,3); + s.scale *= 2.4; + } + } + Wait; + } +} + +Class YnykronSingularityExplosionTrail : Actor +{ + Default + { + RenderStyle "Add"; + +NOBLOCKMAP; + +NOGRAVITY; + +FORCEXYBILLBOARD; + +NOTELEPORT; + +NOINTERACTION; + Scale 3.; + Alpha .2; + } + override void PostBeginPlay() + { + Super.PostBeginPlay(); + Scale *= FRandom[ExploS](0.8,1.1); + Scale.x *= RandomPick[ExploS](-1,1); + Scale.y *= RandomPick[ExploS](-1,1); + } + override void Tick() + { + if ( isFrozen() ) return; + if ( !CheckNoDelay() || (tics == -1) ) return; + if ( tics > 0 ) tics--; + while ( !tics ) + { + if ( !SetState(CurState.NextState) ) + return; + } + } + States + { + Spawn: + XEX4 ABCDEFGHIJKLMNOPQRSTUVWXYZ[\ 1 Bright; + Stop; + } +} Class YnykronSingularityExplosion : Actor { @@ -2010,6 +2096,12 @@ Class YnykronSingularityExplosion : Actor s.angle = ang; s.pitch = pt; } + numpt = Random[ExploS](-1,3); + for ( int i=0; i 0 ) { - Vector3 bounced = d.HitDir-(2*hitnormal*(d.HitDir dot HitNormal)); + Vector3 bounced = d.HitDir-(1.2*hitnormal*(d.HitDir dot HitNormal)); ang = atan2(bounced.y,bounced.x); pt = asin(-bounced.z); origin = d.HitLocation+hitnormal; @@ -2447,7 +2539,7 @@ Class YnykronAltBeam : Actor let b = Spawn("InvisibleSplasher",t.WaterHitList[i].hitpos); b.A_CheckTerrain(); } - for ( int i=0; i 0 ) { - Vector3 bounced = d.HitDir-(2*hitnormal*(d.HitDir dot HitNormal)); + Vector3 bounced = d.HitDir-(1.2*hitnormal*(d.HitDir dot HitNormal)); ang = atan2(bounced.y,bounced.x); pt = asin(-bounced.z); origin = d.HitLocation+hitnormal; @@ -1832,7 +1832,7 @@ Class GoldenSubImpact : Actor totaldist -= d.Distance; if ( totaldist > 0 ) { - Vector3 bounced = d.HitDir-(2*hitnormal*(d.HitDir dot HitNormal)); + Vector3 bounced = d.HitDir-(1.2*hitnormal*(d.HitDir dot HitNormal)); ang = atan2(bounced.y,bounced.x); pt = asin(-bounced.z); origin = d.HitLocation+hitnormal;