Initial commit

This commit is contained in:
patience 2026-04-12 21:39:16 +01:00
commit 9f4b2542cf
No known key found for this signature in database
17 changed files with 598 additions and 0 deletions

369
Effects/transitions.fx Executable file
View file

@ -0,0 +1,369 @@
#ifdef GL_ES
precision mediump float;
#endif
sampler uImage0 : register(s0);
uniform float2 uResolution;
uniform float uTime;
float uProgress;
#define PI 3.14159
// Note: to whomever reads this trying to work out shaders, do NOT bundle them in one file like I have here. This is just an experiment.
float mod(float x, float y){
float z = x;
return z%y;
}
float4 lines(float2 st : TEXCOORD0) : COLOR0 {
float time=uProgress*.06 + .5*PI;
float2 ce = float2(.5,.5);
float2 ef = st;
ef.x=ef.x-0.3*mod(ef.y,0.2) + 0.2*ceil(5.*ef.y);
float4 tex=tex2D(uImage0, st);
float4 gl_FragColor=float4(0,0,0,0);
float3 color = float3(0,0,0);
//float3 notcolor = float3(0,1,0);
float3 notcolor = tex.xyz;
if(sin(time*1.+1.5*PI)>0.){
if(ef.x-1.<sin(time)){
gl_FragColor=float4(notcolor,0.);
}else{
gl_FragColor=float4(color,1.);
}
}else{
if(ef.x-1.<sin(time+PI)){
gl_FragColor=float4(color,1.);
}else{
gl_FragColor=float4(notcolor,0.);
}
}
//if(uProgress/100>st.x){gl_FragColor.r=1.;}
return gl_FragColor;
}
float clam(float x, float minimum, float maximum){
if(x>maximum){return maximum;}
if(x<minimum){return minimum;}
return x;
}
float smooth(float edge0, float edge1, float x){
float t = clam((x - edge0) / (edge1 - edge0), 0.0, 1.0);
return t * t * (3.0 - 2.0 * t);
}
float4 prideful(float2 st : TEXCOORD0) : COLOR0 {
float time=uProgress*.01*2.4;
float4 none=tex2D(uImage0, st);
float4 color=none;
float4 pink=float4(1.,.5,.5,1.);
float4 blue=float4(.5,.7,1.,1.);
for(float i=.0;i<.5;i+=.1){
float4 use=float4(1,1,1,1);
if(i==0. || i==.4){use=blue;}
if(i==.1 || (i>.29 && i<.31)){use=pink;}
float step1=smooth(0.,1.,time-i);
//float step1=time-i;
//float step2=time-i-1.;
float step2=smooth(0.,1.,time-1.-i);
if(abs(st.y-.1-2.*i)<.1 && st.x<step1){color=use;}
if(abs(st.y-.1-2.*i)<.1 && st.x<step2){color=none;}
}
return color;
}
// Work on this one more later.
float4 heart(float2 ef : TEXCOORD0) : COLOR0 {
//float time = uTime*2.;
float time=uProgress;
float2 ce = float2(.5,.5);
//float2 st = gl_FragCoord.xy/u_resolution.xy;
float2 st = ef; //* uResolution.x/uResolution.y;
st.y+=.15;
//st=(st-ce)/(6.0-clam(7.*sin(0.01*uProgress*PI), 0., 5.5))+ce;
if(time>50)st.y+=2.;
st.y-=1.-1.0*cos(0.01*uProgress*PI);
st=(st-ce)/(6.0-clam(7.*sin(0.01*uProgress*PI+0.3), 0., 5.5))+ce;
//st = (st-ce)*(1.0/(time*0.1)) + ce;
//st.y+=sin(time/30.)*0.15;
float3 color = float3(0,0,0);
if (
st.y>ce.y
&& abs(st.x-ce.x) < clam(.4*cos((ce.y-st.y)*PI), 0.0, 1.0)
&& st.y>0. && st.y<1.
|| st.y<ce.y
&& abs(st.x-ce.x)<.4
&& (
length(st-ce+float2(.19,0.))<.21
|| length(st-ce+float2(-.19,0.))<.21
)
){
return tex2D(uImage0, ef);
}
return float4(color,1.0);
}
float4 uparrow(float2 st : TEXCOORD0) : COLOR0 {
float time=3.0*uProgress/100.;
float2 ef = st;
float2 ce = float2(.5,.5);
float3 colour = tex2D(uImage0, ef).rgb;
st.y-=abs(st.x-ce.x)+0.5 + 1.5;
st.y+=time;
if(st.y<ce.x)
colour = float3(0,0,0);
if(st.y+1.5<ce.x)
colour=tex2D(uImage0, ef).rgb;
return float4(colour, 1);
}
float4 downarrow(float2 st : TEXCOORD0) : COLOR0 {
float time=3.0*uProgress/100.;
float2 ef = st;
float2 ce = float2(.5,.5);
float3 colour = tex2D(uImage0, ef).rgb;
st.y+=abs(st.x-ce.x)+0.5;
st.y-=time;
if(st.y<ce.x)
colour = float3(0,0,0);
if(st.y+1.5<ce.x)
colour=tex2D(uImage0, ef).rgb;
return float4(colour, 1);
}
float2 rotate(float2 st,float angle){
float2 ce = float2(.5,.5);
st-=ce;
return float2(
st.x*cos(angle)-st.y*sin(angle),
st.x*sin(angle)+st.y*cos(angle)
)+ce;
}
float3 star(float2 st, float3 colorOld, float3 colorNew){
int PT = 5;
float2 ce = float2(.5,.5);
float angle = 2.*PI/float(PT);
st=rotate(st,-.5*PI);
float3 newt = colorOld;
for(int i=0;i<PT;++i){
st = rotate(st,angle);
float te=st.x-ce.x; // Somehow putting this here makes this function 2 arithmetic operations per loop more efficient - just enough to actually compile with 5 points.
if(
te>0
&& abs(st.y-ce.y)+.5*te<.2
){newt=colorNew;}
}
return newt;
}
float4 starry(float2 st : TEXCOORD0) : COLOR0 {
// int BURST = 1; // Remind me to figure out how to compile things ps_3_0 PROPERLY (without modder's toolkit) so I can increase this a bunch.
float2 ce = float2(.5,.5);
float fP = uProgress;
//float time = abs(sin(uProgress*0.5/PI));
//float2 st = gl_FragCoord.xy/u_resolution.xy;
float3 color2=float3(0,0,0);
float3 color =tex2D(uImage0, st).rgb;
if(fP>50){
fP-=50;
color2=color;
color=float3(0,0,0);
}
float time = fP*0.07;
float2 ef = st;
ef=(ef-ce)/time + ce;
ef = rotate(ef,PI);
color=star(ef,color,color2);
/*float separation = 1./(float(BURST)+1.);
for(int i=0;i<BURST;++i){
float2 ef = st;
float3 offset = float3(
separation*float(i) - (float(BURST)*separation - .5),
0.4*sin(float(i*40)),
separation*float(i)
);
ef+=offset.xy;
float ntime = time - offset.z;
if(ntime<0.)ntime=0.01;
ef=(ef-ce)/(ntime) + ce;
ef=rotate(ef,10.*offset.y+PI);
color=star(ef,color,color2);
}*/
return float4(color,1.0);
}
float4 columns_ordered(float2 st : TEXCOORD0) : COLOR0 {
float BURST = 16.;
float time=uProgress/15. + .5*PI;
float2 ce = float2(.5,.5);
float3 color=tex2D(uImage0, st).rgb;
float ttime = ceil(time/(PI*2.))*PI*2.-PI;
float segment=ceil(BURST*(st.x+ttime))/BURST;
st.y-=.3*sin(4.3*segment);
if(
abs(st.y-ce.y)<sin(time+segment)
){
color=float3(0,0,0);
}
return float4(color,1.);
}
float4 columns_sudden(float2 st : TEXCOORD0) : COLOR0 {
float BURST=16.;
float time=uProgress/(10.*PI);
float2 ce = float2(.5,.5);
float3 color=tex2D(uImage0, st).rgb;
float ttime = ceil(time/(PI*2.) - .2)*PI*2.;
float segment=ceil(BURST*(st.x+ttime))/BURST;
st.y-=.3*sin(4.3*segment);
float pause = abs(st.y-ce.y)+.3;
if(
.8*pause<abs(sin(time+.2*sin(segment*14.)))
){
color=float3(0,0,0);
}
return float4(color,1.);
}
float4 water(float2 st : TEXCOORD0) : COLOR0 {
float time=uProgress/4.+1.5*PI;
float2 ce = float2(.5,.5);
float3 color=tex2D(uImage0, st).rgb;
st.y = 1.-st.y;
st+=.2*sin(time+st.x+.25*PI);
st+=sin(.25*time);
if(st.y<ce.y) color=float3(0,0,0);
return float4(color,1.);
}
float4 wonder(float2 st : TEXCOORD0) : COLOR0 {
float time=uProgress*0.02*PI-.5*PI;
float2 ce = float2(.5,.5);
float2 ef = st;
float3 color=float3(0,0,0);
st=rotate(st,5.*length(st-ce));
st=rotate(st,3.*sin(time));
st.x-=sin(time);
if(st.x-ce.x>abs(.2*sin(st.y*PI+.5*PI)))color=tex2D(uImage0, ef).rgb;
return float4(color,1.);
}
float4 columns_sudden_angled(float2 st : TEXCOORD0) : COLOR0 {
float BURST=9.;
float time=(uProgress+50.)/(10.*PI);
float2 ce = float2(.5,.5);
float3 color2=tex2D(uImage0, st).rgb;
float3 color=float3(0,0,0);
st = rotate(st, 0.25*PI);
float ttime = ceil(time/(PI*2.) - .2)*PI*2.;
float segment=ceil(BURST*(st.x+ttime))/BURST;
st.y-=.4*sin(4.3*segment);
float pause = abs(st.y-ce.y)+.3;
if(
.8*pause<abs(1.2*sin(time+.2*sin(segment*14.)))
){
color=color2;
}
return float4(color,1.);
}
float4 circle(float2 st : TEXCOORD0) : COLOR0 {
//float time=uProgress;
float2 ce = float2(.5,.5);
float4 color=tex2D(uImage0, st);
float4 color2=float4(0,0,0,0);
float time = 60.-1.2*uProgress;
if(time<0.)time=uProgress*1.2-60.; // For some reason just using abs() here causes it not to compile.
//st.x = st.x*(uResolution.y/uResolution.x);
if(length(st-ce)>time*0.02)return color2;
return color;
}
float4 doors(float2 st : TEXCOORD0) : COLOR0 {
float time=uProgress*0.01*PI;
float2 ce = float2(.5,.5);
float4 color2=tex2D(uImage0, st);
float4 color=float4(0,0,0,0);
if(.5-abs(st.x-ce.x)>0.5*sin(time))return color2;
return color;
}
technique Technique1
{
pass Lines {PixelShader = compile ps_2_0 lines();}
pass Prideful {PixelShader = compile ps_2_0 prideful();}
pass Loving {PixelShader = compile ps_2_0 heart();}
pass Rising {PixelShader = compile ps_2_0 uparrow();}
pass Falling {PixelShader = compile ps_2_0 downarrow();}
pass Starry {PixelShader = compile ps_2_0 starry();}
pass Winding {PixelShader = compile ps_2_0 columns_ordered();}
pass Jaws {PixelShader = compile ps_2_0 columns_sudden();}
pass Flooding {PixelShader = compile ps_2_0 water();}
pass Wonder {PixelShader = compile ps_2_0 wonder();}
pass Collapse {PixelShader = compile ps_2_0 columns_sudden_angled();}
pass Circle {PixelShader = compile ps_2_0 circle();}
pass Doors {PixelShader = compile ps_2_0 doors();}
}

BIN
Effects/transitions.xnb Normal file

Binary file not shown.

6
Localization/en-US.hjson Normal file
View file

@ -0,0 +1,6 @@
PridefulHallowTooltip: Made it for a friend a while ago; might as well include it here as well!
DefaultTransitionTooltip:
'''
Determines which shader plays when none are available for your current location,
or anywhere when the Use Biome Specific Transitions config is disabled.
'''

View file

@ -0,0 +1,16 @@
{
"profiles": {
"Terraria": {
"commandName": "Executable",
"executablePath": "$(DotNetName)",
"commandLineArgs": "$(tMLPath)",
"workingDirectory": "$(tMLSteamPath)"
},
"TerrariaServer": {
"commandName": "Executable",
"executablePath": "$(DotNetName)",
"commandLineArgs": "$(tMLServerPath)",
"workingDirectory": "$(tMLSteamPath)"
}
}
}

79
TransitionPlayer.cs Normal file
View file

@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Terraria;
using Terraria.DataStructures;
using Terraria.Graphics.Effects;
using Terraria.ID;
using Terraria.ModLoader;
namespace smoothDeathTransitions {
public class TransitionPlayer : ModPlayer {
/*public override void Kill(double damage, int hitDirection, bool pvp, PlayerDeathReason damageSource)
{
Player.respawnTimer=150; // For testing
}*/
public string GetBiomeSpecificTransitions(){
// This code is going to suck.
if (ModLoader.TryGetMod("CalamityMod", out Mod CalamityMod)){
if((bool)CalamityMod.Call("GetInZone", Player, "SunkenSea")
|| (bool)CalamityMod.Call("GetInZone", Player, "Abyss")
|| (bool)CalamityMod.Call("GetInZone", Player, "SulphurousSea")) return "Flooding";
if((bool)CalamityMod.Call("GetInZone", Player, "AstralInfection"))return "Winding";
}
if(ModLoader.TryGetMod("TheConfectionRebirth", out Mod ConfectionMod) && ConfectionMod.TryFind("ConfectionBiome",out ModBiome ConfectionBiome)){
if(Player.InModBiome(ConfectionBiome)){
if(ModContent.GetInstance<TransitionsConfig>().PridefulHallow)return "Prideful";
return "Wonder";
}
}
if(Player.ZoneShimmer)return "Starry";
if(Player.ZoneDungeon || Player.ZoneLihzhardTemple)return "Doors";
if(Player.ZoneJungle)return "Collapse";
if(Player.ZoneCorrupt)return "Winding";
if(Player.ZoneCrimson)return "Jaws";
if(Player.ZoneHallow){
if(ModContent.GetInstance<TransitionsConfig>().PridefulHallow)return "Prideful";
return "Loving";
}
if(Player.ZoneSnow)return "Wonder";
if(Player.ZoneBeach)return "Flooding";
if(Player.ZoneSkyHeight)return "Rising";
if(Player.ZoneNormalUnderground || Player.ZoneNormalCaverns)return "Circle";
if(Player.ZoneUnderworldHeight)return "Falling";
return ModContent.GetInstance<TransitionsConfig>().DefaultTransition;
}
public int transitionTicker = 0;
public int transitionTime = 200;
public string transitionChosen;
public override void PreUpdate()
{
// Check if appropriate conditions
if(Main.netMode != NetmodeID.Server){
// Check if the time is nigh
if(transitionTicker==0 && Player.dead && Player.respawnTimer<transitionTime/2){
transitionTicker=transitionTime;
if(ModContent.GetInstance<TransitionsConfig>().UseBiomeSpecificTransitions){transitionChosen=GetBiomeSpecificTransitions();}
else{transitionChosen=ModContent.GetInstance<TransitionsConfig>().DefaultTransition;}
if(!Filters.Scene[transitionChosen].IsActive()){
Filters.Scene.Activate(transitionChosen, Player.Center).GetShader();
}
}
if(transitionTicker>0){
--transitionTicker;
float progress = ((float)(transitionTime-transitionTicker)/(float)transitionTime)*100f; // 0-100%
Filters.Scene[transitionChosen].GetShader().UseProgress(progress);
if(transitionTicker==0){
Filters.Scene[transitionChosen].Deactivate();
}
}
}
}
}
}

23
TransitionsConfig.cs Normal file
View file

@ -0,0 +1,23 @@
using System.ComponentModel;
using Terraria.ModLoader.Config;
namespace smoothDeathTransitions
{
public class TransitionsConfig : ModConfig
{
public override ConfigScope Mode => ConfigScope.ClientSide;
[DefaultValue(true)]
public bool UseBiomeSpecificTransitions;
[DefaultValue(false)]
[TooltipKey("$PridefulHallowTooltip")]
public bool PridefulHallow;
[DefaultValue("Lines")]
[TooltipKey("$DefaultTransitionTooltip")]
[DrawTicks]
[OptionStrings(["Lines", "Loving", "Rising", "Falling", "Starry", "Winding", "Jaws", "Flooding", "Wonder", "Collapse", "Circle", "Doors", "Prideful"])]
public string DefaultTransition;
}
}

4
build.txt Normal file
View file

@ -0,0 +1,4 @@
displayName = Smooth Death Transitions
author = Emerald Quartz
side = Client
version = 2.0.0

19
description.txt Normal file
View file

@ -0,0 +1,19 @@
Updates the traditional death screen with smooth transition shaders when you respawn. Fully client-side, does not alter gameplay. Open-source, if you'd like a shader-specific example mod.
Currently available transitions:
- Lines - staggered vertical sweep. Default if biome-specific transitions are disabled.
- Loving - heart boxes in the screen and exits down. Edits pending.
- Rising and Falling - twin upwards and downwards sweeps inspired by their equivalents in Celeste.
- Starry - expanding 5-pointed star.
- Winding - a sort of unzipping-like thing.
- Jaws - series of erratic vertical bars.
- Flooding - waves envelop the screen briefly.
- Wonder - a swirly shading inspired by Rayman Legends.
- Collapse - jagged diagonal letterboxing.
- Circle - simple closing-in circle.
- Doors - two-sided shut and open.
- Prideful - trans flag sweep that optionally replaces the Hallow's ordinary transition.
Explicitly supports Calamity and Confection Rebaked, but all content mods should be fine; it'll just use the default transition.
Successor of the Celeste Death Transition mod, which was a two-hour project I made after getting bored one evening. This one has marginally more thought put into it.

23
description_workshop.txt Normal file
View file

@ -0,0 +1,23 @@
[h1]Smooth Death Transitions[/h1]
Updates the traditional death screen with smooth transition shaders when you respawn. Fully client-side, does not alter gameplay. Open-source, if you'd like a shader-specific example mod.
Currently available transitions:
[list]
[*][b]Lines[/b] - staggered vertical sweep. Default if biome-specific transitions are disabled.
[*][b]Loving[/b] - heart boxes in the screen and exits down. Edits pending.
[*][b]Rising[/b] and [b]Falling[/b] - twin upwards and downwards sweeps inspired by their equivalents in Celeste.
[*][b]Starry[/b] - expanding 5-pointed star.
[*][b]Winding[/b] - a sort of unzipping-like thing.
[*][b]Jaws[/b] - series of erratic vertical bars.
[*][b]Flooding[/b] - waves envelop the screen briefly.
[*][b]Wonder[/b] - a swirly shading inspired by Rayman Legends.
[*][b]Collapse[/b] - jagged diagonal letterboxing.
[*][b]Circle[/b] - simple closing-in circle.
[*][b]Doors[/b] - two-sided shut and open.
[*][b]Prideful[/b] - trans flag sweep that optionally replaces the Hallow's ordinary transition.
[/list]
Explicitly supports Calamity and Confection Rebaked, but all content mods should be fine; it'll just use the default transition.
Successor of the [url=https://steamcommunity.com/sharedfiles/filedetails/?id=3443385596]Celeste Death Transition[/url] mod, which was a short project I made after getting bored one evening. This one has marginally more thought put into it.

20
en-US.hjson Normal file
View file

@ -0,0 +1,20 @@
Mods: {
smoothDeathTransitions: {
Configs: {
TransitionsConfig: {
PridefulHallow: {
Tooltip: ""
Label: Prideful Hallow
}
UseBiomeSpecificTransitions: {
Tooltip: ""
Label: Use Biome Specific Transitions
}
DisplayName: Transitions Config
DefaultTransition.Label: Default Transition
}
}
}
}

BIN
icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

BIN
icon.png~ Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 501 B

BIN
icon21.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

BIN
icon_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

BIN
icon_small.png~ Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

23
smoothDeathTransitions.cs Normal file
View file

@ -0,0 +1,23 @@
using Microsoft.Xna.Framework.Graphics;
using ReLogic.Content;
using Terraria;
using Terraria.Graphics.Effects;
using Terraria.Graphics.Shaders;
using Terraria.ID;
using Terraria.ModLoader;
namespace smoothDeathTransitions
{
public class SmoothDeathTransitions : Mod
{
public string[] transitionsAvailable = ["Lines", "Loving", "Rising", "Falling", "Starry", "Winding", "Jaws", "Flooding", "Wonder", "Prideful", "Collapse", "Circle", "Doors"];
public override void Load(){
if(Main.netMode != NetmodeID.Server){
Asset<Effect> screenRef = Assets.Request<Effect>("Effects/transitions");
for(int i=0;i<transitionsAvailable.Length;i++){
Filters.Scene[transitionsAvailable[i]] = new Filter(new ScreenShaderData(screenRef, transitionsAvailable[i]), EffectPriority.Medium);
}
}
}
}
}

View file

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<!-- Import tModLoader mod properties -->
<Import Project="..\tModLoader.targets" />
<!-- General -->
<PropertyGroup>
</PropertyGroup>
<!-- References -->
<ItemGroup>
</ItemGroup>
</Project>