While I was working on my Metroid do-dads, I came across a rather disappointing fact: The transformation image used for the Distortion Sphere only ever faces right, and there's no way to change this with custom Distortion Spheres if you use the base distortionsphere.lua as a requirement. This can result in some rather "interesting" scenarios, like what you see below. Right https://gyazo.com/521d0b7927cdbc34083853b429f2ee2b Left https://gyazo.com/96d5f27e97c3331c9eaea81ac7447408 Of course, me being the aesthetic perfectionist that I am, I immediately set out to remedy this. And what I found is that you can circumvent that problem rather easily, with a bit of know-how. All I had to do is stop using Distortion Spheres, and start using Morph Balls! 1. Copy distortionsphere.lua and all related files from the base tech folder, and put them in your modded tech folder. Rename them all to whatever you want your new base sphere to be. 2. Open each of the files, ctrl+F to replace "distortionsphere" with whatever you named your new tech. 3. Find the section that defines "function activate()" around line 180. It should look something like this: Code: function activate() if not self.active then animator.burstParticleEmitter("activateParticles") animator.playSound("activate") animator.setAnimationState("ballState", "activate") self.angularVelocity = 0 self.angle = 0 end tech.setParentHidden(true) tech.setParentOffset({0, positionOffset()}) tech.setToolUsageSuppressed(true) status.setPersistentEffects("movementAbility", {{stat = "activeMovementAbilities", amount = 1}}) self.active = true end You'll need to replace the first section with something that can detect direction, and luckily Starbound makes this pretty easy with its mcontroller hooks. We make one section checking if the player is facing right (facingDirection returns a value of 1 if so), and one checking for left (facingDirection returns -1), then assign ballState values to each. Code: function activate() if not self.active and mcontroller.facingDirection() > 0 then animator.burstParticleEmitter("activateParticles") animator.playSound("activate") animator.setAnimationState("ballState", "activate_right") self.angularVelocity = 0 self.angle = 0 elseif not self.active and mcontroller.facingDirection() < 0 then animator.burstParticleEmitter("activateParticles") animator.playSound("activate") animator.setAnimationState("ballState", "activate_left") self.angularVelocity = 0 self.angle = 0 end tech.setParentHidden(true) tech.setParentOffset({0, positionOffset()}) tech.setToolUsageSuppressed(true) status.setPersistentEffects("movementAbility", {{stat = "activeMovementAbilities", amount = 1}}) self.active = true end You'll need to do the same for the "function deactivate()" section as well, which is a bit trickier thanks to the check for if the player isn't in sphere form. Code: function deactivate() if self.active and mcontroller.facingDirection() > 0 then animator.burstParticleEmitter("deactivateParticles") animator.playSound("deactivate") animator.setAnimationState("ballState", "deactivate_right") elseif self.active and mcontroller.facingDirection() < 0 then animator.burstParticleEmitter("deactivateParticles") animator.playSound("deactivate") animator.setAnimationState("ballState", "deactivate_left") else animator.setAnimationState("ballState", "off") end animator.stopAllSounds("forceDeactivate") animator.setGlobalTag("ballDirectives", "") tech.setParentHidden(false) tech.setParentOffset({0, 0}) tech.setToolUsageSuppressed(false) status.clearPersistentEffects("movementAbility") self.angle = 0 self.active = false end Now you'll need to make some tweaks to your .animation file. Currently, it only contains info for the Vanilla activate and deactivate states, which no longer exist for our tech thanks to the tweaks we've made here. Thankfully, this is even easier. It's really just a game of copy-paste at this point, so I'll let you spot the differences. Code: { "globalTagDefaults" : { "rotationFrame" : "0", "ballDirectives" : "" }, "animatedParts" : { "stateTypes" : { "ballState" : { "default" : "off", "states" : { "deactivate_left" : { "frames" : 4, "cycle" : 0.1, "mode" : "transition", "transition" : "off" }, "deactivate_right" : { "frames" : 4, "cycle" : 0.1, "mode" : "transition", "transition" : "off" }, "off" : { }, "activate_left" : { "frames" : 4, "cycle" : 0.1, "mode" : "transition", "transition" : "on" }, "activate_right" : { "frames" : 4, "cycle" : 0.1, "mode" : "transition", "transition" : "on" }, "on" : { } } } }, "parts" : { "ballGlow" : { "properties" : { "transformationGroups" : [ "ball" ], "centered" : true }, "partStates" : { "ballState" : { "on" : { "properties" : { "zLevel" : 1, "fullbright" : true, "image" : "<partImage>:<rotationFrame><ballDirectives>" } } } } }, "ball" : { "properties" : { "transformationGroups" : [ "ball" ], "centered" : true }, "partStates" : { "ballState" : { "deactivate_right" : { "properties" : { "offset" : [0, 0], "fullbright" : false, "image" : "transform_right.png:deactivate.<frame>" } }, "deactivate_left" : { "properties" : { "offset" : [0, 0], "fullbright" : false, "image" : "transform_left.png:deactivate.<frame>" } }, "activate_right" : { "properties" : { "offset" : [0, 1.5], "fullbright" : false, "image" : "transform_right.png:activate.<frame>" } }, "activate_left" : { "properties" : { "offset" : [0, 1.5], "fullbright" : false, "image" : "transform_left.png:activate.<frame>" } }, "on" : { "properties" : { "image" : "<partImage>:<rotationFrame><ballDirectives>" } } } } } } }, "transformationGroups" : { "ball" : { "interpolated" : true } }, "particleEmitters" : { "activateParticles" : { "particles" : [ ] }, "deactivateParticles" : { "particles" : [ ] } }, "sounds" : { "activate" : [ "/sfx/tech/morph.ogg" ], "deactivate" : [ "/sfx/tech/stand.ogg" ], "forceDeactivate" : [ "/sfx/tech/stand.ogg" ] } } Now you're free to make your own transformation images and apply them to the different left and right-facing transformations! Just make sure that if you're only flipping the transform image for your left image that you reverse the order of the aliases defined in your transform_left.animation, so that they play in the proper order when called in-game. You can also remove the white fade effect from the transition pretty simply. All you have to do is delete any line referencing "fade" from your sphere tech's .lua file, and any derived from it. You could also just tweak the color by editing this line here: Code: animator.setGlobalTag("ballDirectives", string.format("?fade=FFFFFFFF;%.1f", math.min(1.0, self.transformFadeTimer / (self.transformFadeTime - 0.15)))) The row of Fs you see there sets the color and brightness, following RGB-L format. Put all of this together, and you wind up with something unique to your tech that you can edit as you please! https://gyazo.com/e103c29e16cbae8d3d21b77e62bccf41 Bug tax: https://gyazo.com/a394d9de38a83f18bb9af148d2bd785b
Got it figured out. Will post results and findings in the morning when I'm less tired. Next step: Remove the white fade effect. Edit: Removed the white fade in a matter of minutes, working up OP now.
Theres also animator.setFlipped() which could be useful in this instance. Code: animator.setFlipped(mcontroller.facingDirection() < 0) That should flip the animation when the mcontroller is facing left.
Yeah, I noticed that when I started digging through the code of the Dash abilities for use with the Speed Booster, and I plan to streamline my code at some point to also use that feature. The biggest problem I'm seeing when it comes to Starbound modding is the lack of "proper" tutorials, and of comments in code that explain what the different bits do, which led to me not knowing how to set up the arguments or this function for the longest time. I probably won't be the first person to do it, but I intend to help break this trend by making thorough comments on my code for the inevitable folks who unpack my work later.
Okay, for anyone else coming here, do not use animator.setFlipped(), as it will carry over to the Distortion Sphere. You'd have to find some way to actively fix that issue while morphed.