From 96de20ee57c67c56ecfc6c8ce7266f3342302a13 Mon Sep 17 00:00:00 2001 From: inkoalawetrust <56005600+inkoalawetrust@users.noreply.github.com> Date: Fri, 20 Sep 2024 01:37:51 +0300 Subject: [PATCH] Emplacements use visual thinker fake operators. Emplacements now use a VisualThinker for the fake operator visual effect, as I originally intended. Thanks to DileepVR helping me get the damn sprite rotation code working finally. Also helps bypass this engine bug (https://github.com/ZDoom/gzdoom/issues/2716) on the placeholder actor version of the effect. --- ZScript/Bases/Base.zsc | 70 ++++++++++++ ZScript/Bases/Humanoid/Emplacement.zsc | 149 +++++++------------------ 2 files changed, 113 insertions(+), 106 deletions(-) diff --git a/ZScript/Bases/Base.zsc b/ZScript/Bases/Base.zsc index 16f90fb..29ce65f 100644 --- a/ZScript/Bases/Base.zsc +++ b/ZScript/Bases/Base.zsc @@ -5,7 +5,77 @@ Class KAI_MixinActor : Actor Abstract Mixin KAI_UniversalFunctions; Mixin KAI_CheckFunctions; } +Class emit : Actor +{ + TextureID tex; + Default + { + +NOINTERACTION + +NOBLOCKMAP + +BRIGHT + Scale 0.25; + } + + override void PostBeginPlay() + { + Super.PostBeginPlay(); + tex = TexMan.CheckForTexture("TRCHA1"); + } + + States + { + Spawn: + MISL A 1; + Looping: + MISL A 1 + { + angle = random(0,359); + pitch = random(-90,90); + Vel3DFromAngle(random(2,6), angle, pitch); + let p = Level.SpawnVisualThinker("ZRocketBoom"); + if (p) + { + p.Texture = tex; + p.pos = pos; + p.vel = vel; + p.scolor = "FF0000"; + p.SetRenderStyle(STYLE_Add); + p.flags = SPF_ROLL|SPF_FULLBRIGHT; + p.roll = random(0,359); + p.alpha = 1.0; + p.Scale = (1,1); + } + vel = (0,0,0); + + } + Loop; + } +} +Class ZRocketBoom : VisualThinker +{ + double RollVel; + + override void PostBeginPlay() + { + Super.PostBeginPlay(); + RollVel = frandom(-10.0, 10.0); + Alpha = 1.0; + } + + override void Tick() + { + if (bDESTROYED || IsFrozen()) + return; + + Super.Tick(); + Roll += RollVel; + Alpha -= 0.05; + if (Alpha <= 0.0) + Destroy(); + + } +} Class KAI_Actor : Actor Abstract { Default diff --git a/ZScript/Bases/Humanoid/Emplacement.zsc b/ZScript/Bases/Humanoid/Emplacement.zsc index 4cddd16..9a31bda 100644 --- a/ZScript/Bases/Humanoid/Emplacement.zsc +++ b/ZScript/Bases/Humanoid/Emplacement.zsc @@ -1,9 +1,3 @@ -//TODO: Uh, I am JUST getting started with this new major feature, very unsure how ANYTHING should look like. -//- I guess KAI_Emplacement probably doesn't need to be based on KAI_Actor, it's basically an interactive prop. -//- Figure out the minor (Huge) design issue of how to map an NPC using an emplacement to the proper morph. And also the same problem but with player skins. Fun!!!!! - //- Will probably need an associative map, at least for mapping NPC operators to the correct morphs. i.e KAI_HellKnight = HellKnightMorph, KAI_Imp = ImpMorph etc -//- Maybe add a basic player morph class? Or rather the handling for a purely visual pseudo-player that can move relative to the emplacement, for basic morph classes. - //The base emplacement class for the library. Emplacements can be used by both players and KAI_Humanoid NPCs by default. Class KAI_Emplacement : Actor Abstract { @@ -157,7 +151,22 @@ Class KAI_Emplacement : Actor Abstract } //Create a fake operator visual effect to serve as a placeholder for NPC and player operators if you have no unique emplacement sprites. - Actor CreateFakeOperator (Vector3 Position) + VisualThinker CreateFakeOperator (Vector3 Offsets = (0,0,0)) + { + Let Illusion = KAI_EmplacementFakeOperator(Level.SpawnVisualThinker("KAI_EmplacementFakeOperator")); + If (Illusion) + { + Illusion.Pos = Level.Vec3Offset (Pos,Offsets); + Illusion.Offsets = Level.Vec3Diff (Pos, Illusion.Pos); + Illusion.Operator = Operator; + Illusion.Emplacement = Self; + Illusion.Texture = CurState.GetSpriteTexture (0); //Just get some placeholder graphic for now so the thinker won't immediately self-destruct. + Return Illusion; + } + Return Null; + } + //Create a fake operator visual effect to serve as a placeholder for NPC and player operators if you have no unique emplacement sprites. + /*Actor CreateFakeOperator (Vector3 Position) { Let FakeOp = KAI_EmplacementFakeOperator(Spawn ("KAI_EmplacementFakeOperator",Level.Vec3Offset(Pos,Position))); @@ -170,7 +179,7 @@ Class KAI_Emplacement : Actor Abstract } Return FakeOp; - } + }*/ } Class KAI_EmplacementNPC : KAI_Actor Abstract @@ -263,127 +272,48 @@ Class KAI_EmplacementPlayer : PlayerPawn } } -//HACK: I can't get the sprite rotation math right on the intended VisualThinker version. And nobody can help me with it. So this serves as a placeholder class. -Class KAI_EmplacementFakeOperator : Actor +Class KAI_EmplacementFakeOperator : VisualThinker { Vector3 Offsets; Actor Operator; KAI_Emplacement Emplacement; Mixin KAI_CheckFunctions; State SpriteState; //The state which we get the sprite to use. - //Int PlayerSkinID; //The number of the players' skin. Only relevant if the operator is both a player, and of course, is using a skin. - - Name SpriteName; - - Override Void PostBeginPlay() - { - Super.PostBeginPlay(); - - //Set the first idle frame of the operator as the texture. - If (Operator) - { - //Acquire the first valid see state sprite of the operator to use as the fallback graphic. If the graphic is TNT1A0, look for the next state's sprite. - { - Int SkinNum = Emplacement.OperatorMorph.Player ? Emplacement.OperatorMorph.Player.GetSkin() : 0; - State LeState = GetDefaultByType(Operator.GetClass()).SeeState; - TextureID Graphic; - For (Int I; I < 32; I++) - { - LeState = LeState.NextState; - Graphic = LeState.GetSpriteTexture (0,SkinNum); - } - String SpriteString; - SpriteString = TexMan.GetName(Graphic); - SpriteString.Truncate (4); - SpriteName = SpriteString; - SpriteState = LeState; - } - } - } - Override Void Tick() - { - If (!Operator || !Emplacement || !KAI_Emplacement(Emplacement).Operator) - { - Destroy(); - Return; - } - - If (IsFrozen()) - Return; - - SetOrigin(KAI_Math.Vec3OffsetRelative (Emplacement, Offsets),True); - A_Face (Emplacement); - - // Advance the state - if (tics != -1) - { - if (tics > 0) tics--; - while (!tics) - { - if (!SetState (CurState.NextState)) - { // mobj was removed - return; - } - } - } - } - - States - { - Spawn: - #### A 1 - { - If (SpriteState) - { - Sprite = GetSpriteIndex(SpriteName); - Frame = SpriteState.Frame; - } - } - Loop; - } -} - -/*Class KAI_EmplacementFakeOperator : VisualThinker -{ - Vector3 Offsets; - Actor Operator; - Actor Emplacement; - Mixin KAI_CheckFunctions; - State SpriteState; //The state which we get the sprite to use. Int PlayerSkinID; //The number of the players' skin. Only relevant if the operator is both a player, and of course, is using a skin. - //Cut down version of GetSpriteAngleFromPos(). + //Cut down version of GetSpriteAngleFromPos(). + //CREDIT: DileepVR for helping me fucking finally get this stupid shit to work. + /*NOTE: OH YEAH, WHEN *YOU* USE THIS IN CONJUNCTION WITH GETSPRITETEXTURE() IN YOUR OWN CODE, ALSO MAKE SURE TO TAKE ITS' SECOND RETURN TO CONTROL IF THE + VISUALTHINKER SHOULD BE FLIPPED.*/ Int FakeOpGetSpriteAngle (Vector3 CamPos, Bool SixteenAngles) { Vector3 Coords = Level.SphericalCoords (Pos,CamPos); Double Ang = -Coords.X; - Double Angle = Emplacement.Angle + 180; + Double Angle = Emplacement.Angle - 180; //This code's for a visualthinker, so no angle of its' own, so it takes the angle of the actor it's attached to. Double SprAng = Angle - Ang; Double Result; If (!SixteenAngles) - { - Result = BAM (SprAng - (Angle/* + SpriteRotation/) + 45.0 / 2 * 9) >> 28; - } + Result = BAM (-SprAng + 45.0 / 2 * 9) >> 28; Else - { - Result = BAM (SprAng - (Angle/* + SpriteRotation/) + 45.0 / 2 * 9 - 180.0 / 16) >> 28; - } + Result = BAM (-SprAng + 45.0 / 2 * 9 - 180.0 / 16) >> 28; Return Int(Result); } + Override Void PostBeginPlay() { Super.PostBeginPlay(); + Flags = SPF_NO_XY_BILLBOARD; //Set the first idle frame of the operator as the texture. - //TODO: Need to also make the sprites have working rotations, fuck... If (Operator) { //If (!Texture) //Acquire the first valid see state sprite of the operator to use as the fallback graphic. If the graphic is TNT1A0, look for the next state's sprite. { - Int SkinNum = Operator.Player ? Operator.Player.GetSkin() : 0; + Translation = Operator.Translation; + Int SkinNum = Emplacement.OperatorMorph.Player ? Emplacement.OperatorMorph.Player.GetSkin() : 0; State LeState = GetDefaultByType(Operator.GetClass()).SeeState; TextureID Graphic = LeState.GetSpriteTexture (0,SkinNum); For (Int I; I < 32; I++) @@ -396,11 +326,8 @@ Class KAI_EmplacementFakeOperator : Actor SpriteState = LeState; Texture = Graphic; PlayerSkinID = SkinNum; - console.printf ("fake operator: took actors' idle sprite (%s)",texman.getname(texture)); } } - Else - {console.printf ("fake operator: no actual operator");Destroy();} } override void ondestroy(){console.printf ("fake operator: we got removed for some other reason");if (!Texture) console.printf ("cuz we got no texture");} Override Void Tick() @@ -408,15 +335,25 @@ Class KAI_EmplacementFakeOperator : Actor Super.Tick(); If (!Operator || !Emplacement || !KAI_Emplacement(Emplacement).Operator) - {console.printf ("fake operator: no operator or emplacement"); + { Destroy(); Return; } - Texture = SpriteState.GetSpriteTexture (FakeOpGetSpriteAngle(Players[ConsolePlayer].Camera.Pos,True),PlayerSkinID); + If (Players[ConsolePlayer].Camera) + { + If (PlayerSkinID != 0) + [Texture,bXFlip,Scale] = SpriteState.GetSpriteTexture (FakeOpGetSpriteAngle(Players[ConsolePlayer].Camera.Pos,True),PlayerSkinID); + Else //GetSpriteTexture's scale return is only for skins. + { + Vector2 Garbage; + [Texture,bXFlip,Garbage] = SpriteState.GetSpriteTexture (FakeOpGetSpriteAngle(Players[ConsolePlayer].Camera.Pos,True),PlayerSkinID); + } + } + //console.printf ("RENDERING STATS: GRAPHIC %s, MIRRORED %d, SCALE %.2f %.2f",texman.getname(texture),bxflip,scale); If (IsFrozen()) Return; - Pos = KAI_Math.Vec3OffsetRelative (Emplacement, Offsets); + Pos = KAI_Math.Vec3OffsetRelative (Emplacement, Offsets,flags:KAI_Math.V3R_ANGLEONLY); } -}*/ \ No newline at end of file +} \ No newline at end of file