HeavenStudio/Assets/Scripts/Games/KarateMan/KarateMan.cs
AstrlJelly b044d400c4 it compiles now
this Background Appearance block got hands ‼️
working on converting everything to the new bg color system
this will be so annoying to build a RiqUpdater for.
2023-08-21 00:25:15 -04:00

1243 lines
54 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HeavenStudio.Util;
using Jukebox;
using System.Linq;
namespace HeavenStudio.Games.Loaders
{
using static Minigames;
public static class RvlNewKarateLoader
{
public static Minigame AddGame(EventCaller eventCaller)
{
RiqEntity WarningUpdater(string datamodel, RiqEntity entity)
{
if (datamodel == "karateman/hitX")
{
int newWarning = (int)entity["type"];
if (entity["type"] < 7) {
newWarning++;
} else {
newWarning = 0;
}
entity.CreateProperty("whichWarning", newWarning);
entity.CreateProperty("customLength", false);
entity.CreateProperty("cutOut", true);
entity.dynamicData.Remove("type");
entity.datamodel = "karateman/warnings";
return entity;
}
return null;
}
RiqBeatmap.OnUpdateEntity += WarningUpdater;
RiqEntity BackgroundUpdater(string datamodel, RiqEntity entity)
{
if (datamodel == "karateman/set background effects")
{
return entity;
}
return null;
}
RiqBeatmap.OnUpdateEntity += BackgroundUpdater;
/*
RiqEntity NameUpdater(string datamodel, RiqEntity entity)
{
if (entity.datamodel.Split('/')[0] == "karateman")
{
Debug.Log(datamodel);
// this was the only way i could figure out how to convert from that freaky format into an actual color :(
// if (entity.dynamicData.ContainsKey("colorA")) {
// for (int i = 0; i < (entity.dynamicData.ContainsKey("colorB") ? 4 : 1); i++)
// {
// string whichColor = i switch {
// 0 => "colorA",
// 1 => "colorB",
// 2 => "colorC",
// _ => "colorD",
// };
// string[] tempValues = entity[whichColor].ToString().Split(": ");
// List<float> values = new();
// foreach (string value in tempValues)
// {
// string temp = string.Join("", value.Where(x => x == '.' || char.IsDigit(x)));
// if (temp != string.Empty) values.Add(float.Parse(temp));
// }
// entity[whichColor] = new Color(values[0], values[1], values[2]);
// }
// }
entity.datamodel = entity.datamodel.Remove(0, 9);
entity.datamodel = "karateMan" + entity.datamodel;
return entity;
} else if (entity.datamodel == "gameManager/switchGame/karateman") {
entity.datamodel = "gameManager/switchGame/karateMan";
}
return null;
}
RiqBeatmap.OnUpdateEntity += NameUpdater;
*/
return new Minigame("karateman", "Karate Man", "fbca3e", false, false, new List<GameAction>()
{
new GameAction("test", "Test")
{
function = delegate { Debug.Log(eventCaller.currentEntity["string"]); },
resizable = true,
parameters = new List<Param>()
{
new Param("bool", true, "Disable Below When Inactive", "Whether to bop to the beat or not"),
new Param("string", "test", "Will Get Disabled", "Disable When Above Is Inactive")
},
},
new GameAction("bop", "Bop")
{
function = delegate { var e = eventCaller.currentEntity; KarateMan.instance.ToggleBop(e.beat, e.length, e["toggle2"], e["toggle"]); },
resizable = true,
parameters = new List<Param>()
{
new Param("toggle2", true, "Bop", "Whether to bop to the beat or not"),
new Param("toggle", false, "Bop (Auto)", "Whether to auto bop to the beat or not")
},
},
new GameAction("hit", "Toss Object") {
function = delegate {
var e = eventCaller.currentEntity;
KarateMan.instance.CreateItem(e.beat, e["type"], e["type2"]);
KarateMan.CreateItemSFX(e.beat, e["type"], e["mute"]);
},
inactiveFunction = delegate {
var e = eventCaller.currentEntity;
KarateMan.QueueItem(e.beat, e["type"], e["type2"]);
KarateMan.CreateItemSFX(e.beat, e["type"], e["mute"]);
},
defaultLength = 2,
parameters = new List<Param>()
{
new Param("type", KarateMan.HitType.Pot, "Object", "The object to fire"),
new Param("type2", KarateMan.KarateManFaces.Normal, "Success Expression", "The facial expression to set Joe to on hit"),
new Param("mute", false, "Mute", "Should the throwing sound be muted?"),
}
},
new GameAction("bulb", "Toss Lightbulb")
{
function = delegate {
var e = eventCaller.currentEntity;
KarateMan.instance.CreateBulbSpecial(e.beat, e["type"], e["colorA"], e["type2"]);
KarateMan.CreateItemSFX(e.beat, e["type"], false, true);
},
inactiveFunction = delegate {
var e = eventCaller.currentEntity;
KarateMan.QueueBulb(e.beat, e["type"], e["colorA"], e["type2"]);
KarateMan.CreateItemSFX(e.beat, e["type"], false, true);
},
defaultLength = 2,
parameters = new List<Param>()
{
new Param("type", KarateMan.LightBulbType.Normal, "Type", "The preset bulb type. Yellow is used for kicks while Blue is used for combos"),
new Param("colorA", new Color(1f,1f,1f), "Custom Color", "The color to use when the bulb type is set to Custom"),
new Param("type2", KarateMan.KarateManFaces.Normal, "Success Expression", "The facial expression to set Joe to on hit"),
new Param("mute", false, "Mute", "Should the throwing sound be muted?"),
},
},
new GameAction("kick", "Special: Kick")
{
function = delegate {
var e = eventCaller.currentEntity;
KarateMan.instance.Kick(e.beat, e["toggle"], e["type"], e["cutOut"], e["disableVoice"]);
KarateMan.KickSFX();
},
inactiveFunction = delegate {
var e = eventCaller.currentEntity;
KarateMan.QueueKick(e.beat, e["toggle"], e["type"], e["cutOut"], e["disableVoice"]);
KarateMan.KickSFX();
},
defaultLength = 4f,
parameters = new List<Param>()
{
new Param("toggle", false, "Contains Ball", "Barrel contains a ball instead of a bomb?"),
new Param("type", KarateMan.KarateManFaces.Smirk, "Success Expression", "The facial expression to set Joe to on hit"),
new Param("cutOut", true, "Cut Out Voice", "Will this cue be cut out by another voice?"),
new Param("disableVoice", false, "Disable Voice", "When enabled, there will be no voice during this cue"),
}
},
new GameAction("combo", "Special: Combo")
{
function = delegate {
var e = eventCaller.currentEntity;
KarateMan.instance.Combo(e.beat, e["type"], e["cutOut"], e["disableVoice"]);
KarateMan.ComboSFX();
},
inactiveFunction = delegate {
var e = eventCaller.currentEntity;
KarateMan.QueueCombo(e.beat, e["type"], e["cutOut"], e["disableVoice"]);
KarateMan.ComboSFX();
},
defaultLength = 4,
parameters = new List<Param>()
{
new Param("type", KarateMan.KarateManFaces.Happy, "Success Expression", "The facial expression to set Joe to on hit"),
new Param("cutOut", true, "Cut Out Voice", "Will this cue be cut out by another voice?"),
new Param("disableVoice", false, "Disable Voice", "When enabled, there will be no voice during this cue"),
}
},
new GameAction("warnings", "Warnings")
{
function = delegate {
var e = eventCaller.currentEntity;
KarateMan.instance.DoWord(e.beat, e.length, e["whichWarning"], e["customLength"]);
},
defaultLength = 1f,
resizable = true,
parameters = new List<Param>()
{
new Param("whichWarning", KarateMan.HitThree.HitThree, "Which Warning", "The warning text to show and the sfx to play"),
new Param("customLength", false, "Custom Length", "Have the warning text appear for the length of the block"),
new Param("cutOut", true, "Cut Out Voice", "Will this cue be cut out by another voice?"),
},
inactiveFunction = delegate {
var e = eventCaller.currentEntity;
KarateMan.DoWordSound(e.beat, e.length, e["whichWarning"], e["customLength"]);
}
},
new GameAction("special camera", "Special Camera")
{
function = delegate { var e = eventCaller.currentEntity; KarateMan.DoSpecialCamera(e.beat, e.length, e["toggle"]); },
defaultLength = 8f,
resizable = true,
parameters = new List<Param>()
{
new Param("toggle", true, "Return Camera", "Camera zooms back in?"),
},
inactiveFunction = delegate { var e = eventCaller.currentEntity; KarateMan.DoSpecialCamera(e.beat, e.length, e["toggle"]); }
},
new GameAction("prepare", "Preparation Stance")
{
function = delegate { var e = eventCaller.currentEntity; KarateMan.instance.Prepare(e.beat, e.length);},
resizable = true,
},
new GameAction("set gameplay modifiers", "Flow/Gameplay Modifiers")
{
function = delegate { var e = eventCaller.currentEntity; KarateMan.instance.SetGameplayMods(e.beat, e["type"], e["toggle"]); },
defaultLength = 0.5f,
parameters = new List<Param>()
{
new Param("type", KarateMan.NoriMode.None, "Flow Bar type", "The type of Flow bar to use"),
new Param("toggle", true, "Enable Combos", "Allow the player to combo? (Contextual combos will still be allowed even when off)"),
new Param("toggle2", true, "Enable Kicks", "Allow the player to kick? (Contextual kicks will still be allowed even when off)"),
},
},
new GameAction("background appearance", "Background Appearance")
{
function = delegate {
var e = eventCaller.currentEntity;
KarateMan.instance.BackgroundColor(e.beat, e.length, e["presetBg"], e["shadowType"], e["fxType"], e["startColor"], e["endColor"], e["bgEase"]);
//KarateMan.instance.SetBgTexture(e["type4"], e["type5"], e["colorC"], e["colorD"]);
},
defaultLength = 0.5f,
resizable = true,
parameters = new List<Param>()
{
new Param("presetBg", KarateMan.BackgroundType.Yellow, "Preset Background Type", "The preset background type (will by default fade from the existing )"),
new Param("startColor", new Color(0.985f, 0.79f, 0.243f), "Start Background Color", "The background color to use when background type is set to Custom"),
new Param("endColor", new Color(0.985f, 0.79f, 0.243f), "End Background Color", "When using the Fade background effect, make filter colour fade to this colour"),
new Param("bgEase", Util.EasingFunction.Ease.Instant, "Ease", "Ease to use when fading color"),
new Param("shadowType", KarateMan.ShadowType.Tinted, "Shadow Type", "The shadow type. If Tinted doesn't work with your background color try Custom"),
new Param("shadowColor", new Color(), "Custom Shadow Color", "The shadow color to use when shadow type is set to Custom. When fading the background colour shadows fade to this color"),
new Param("fxType", KarateMan.BackgroundFXType.None, "FX Type", "The background effect to be displayed. Fade uses the entity length to determine colour fading speed"),
new Param("type4", KarateMan.BackgroundTextureType.Plain, "Texture", "The type of background texture to use"),
new Param("type5", KarateMan.ShadowType.Tinted, "Color Filter Type", "The method used to apply colour to the texture"),
new Param("colorC", new Color(), "Custom Filter Color", "The filter color to use when color filter type is set to Custom"),
new Param("colorD", new Color(), "Fading Filter Color", "When using the Fade background effect, make filter colour fade to this colour"),
},
},
// new GameAction("set background effects", "Background Appearance (OLD)")
// {
// function = delegate {
// var e = eventCaller.currentEntity;
// KarateMan.instance.SetBgAndShadowCol(e.beat, e.length, e["type"], e["type2"], e["colorA"], e["colorB"], e["type3"]);
// KarateMan.instance.SetBgTexture(e["type4"], e["type5"], e["colorC"], e["colorD"]);
// },
// defaultLength = 0.5f,
// resizable = true,
// parameters = new List<Param>()
// {
// new Param("type", KarateMan.BackgroundType.Yellow, "Background Type", "The preset background type"),
// new Param("type2", KarateMan.ShadowType.Tinted, "Shadow Type", "The shadow type. If Tinted doesn't work with your background color try Custom"),
// new Param("colorA", new Color(), "Custom Background Color", "The background color to use when background type is set to Custom"),
// new Param("colorB", new Color(), "Custom Shadow Color", "The shadow color to use when shadow type is set to Custom. When fading the background colour shadows fade to this color"),
// new Param("type3", KarateMan.BackgroundFXType.None, "FX Type", "The background effect to be displayed. Fade uses the entity length to determine colour fading speed"),
// new Param("type4", KarateMan.BackgroundTextureType.Plain, "Texture", "The type of background texture to use"),
// new Param("type5", KarateMan.ShadowType.Tinted, "Color Filter Type", "The method used to apply colour to the texture"),
// new Param("colorC", new Color(), "Custom Filter Color", "The filter color to use when color filter type is set to Custom"),
// new Param("colorD", new Color(), "Fading Filter Color", "When using the Fade background effect, make filter colour fade to this colour"),
// },
// },
new GameAction("set object colors", "Object Colors")
{
function = delegate { var e = eventCaller.currentEntity; KarateMan.UpdateMaterialColour(e["colorA"], e["colorB"], e["colorC"]); },
defaultLength = 0.5f,
parameters = new List<Param>()
{
new Param("colorA", new Color(1,1,1,1), "Joe Body Color", "The color to use for Karate Joe's body"),
new Param("colorB", new Color(0.81f,0.81f,0.81f,1), "Joe Highlight Color", "The color to use for Karate Joe's highlights"),
new Param("colorC", new Color(1,1,1,1), "Item Color", "The color to use for the thrown items"),
},
},
new GameAction("particle effects", "Particle Effects")
{
function = delegate { var e = eventCaller.currentEntity; KarateMan.instance.SetParticleEffect(e.beat, e["type"], e["valA"], e["valB"]); },
defaultLength = 0.5f,
parameters = new List<Param>()
{
new Param("type", KarateMan.ParticleType.None, "Particle Type", "The type of particle effect to spawn. Using \"None\" will stop all effects"),
new Param("valA", new EntityTypes.Float(0f, 64f, 1f), "Wind Strength", "The strength of the particle wind"),
new Param("valB", new EntityTypes.Float(1f, 16f, 1f), "Particle Intensity", "The intensity of the particle effect")
},
},
new GameAction("force facial expression", "Set Facial Expression")
{
function = delegate { KarateMan.instance.SetFaceExpression(eventCaller.currentEntity["type"]); },
defaultLength = 0.5f,
resizable = true,
parameters = new List<Param>()
{
new Param("type", KarateMan.KarateManFaces.Normal, "Facial Expression", "The facial expression to force Joe to. Special moves may override this")
}
},
// hidden but here so that the block can update
new GameAction("hitX", "Warnings (old)")
{
hidden = true,
},
},
new List<string>() {"agb", "ntr", "rvl", "ctr", "pco", "normal"},
"karate", "en",
new List<string>() {"en"}
);
}
}
}
namespace HeavenStudio.Games
{
using Scripts_KarateMan;
public class KarateMan : Minigame
{
static List<QueuedObject> queuedObjects = new();
static List<QueuedObject> queuedBulbs = new();
struct QueuedObject
{
public double beat;
public int type;
public int expression;
public Color color;
}
static List<QueuedSpecial> queuedKicks = new();
static List<QueuedSpecial> queuedCombos = new();
struct QueuedSpecial
{
public double beat;
public int expression;
public bool cutOut;
public bool noVoice;
public bool ball;
}
public static KarateMan instance;
public enum HitType
{
Pot = 0,
Lightbulb = 1,
Rock = 2,
Ball = 3,
CookingPot = 6,
Alien = 7,
Bomb = 8,
TacoBell = 999
}
public enum HitThree
{
HitOne,
HitTwo,
HitThree,
HitThreeAlt,
HitFour,
Grr,
Warning,
Combo,
}
public enum LightBulbType
{
Normal,
Blue,
Yellow,
Custom
}
public enum BackgroundType
{
Yellow,
Fuchsia,
Blue,
Red,
Orange,
Pink,
Custom
}
public enum BackgroundFXType
{
None,
Sunburst,
Rings,
Fade
}
public enum BackgroundTextureType
{
Plain,
Gradient,
Radial,
Blood,
//ManMan?
}
public enum ShadowType
{
Tinted,
Custom
}
public enum CameraAngle
{
Normal,
Special
}
public enum ParticleType
{
None,
Snow,
Fire,
Rain
}
public enum KarateManFaces
{
Normal,
Smirk,
Surprise,
Sad,
Lenny,
Happy,
VerySad,
Blush
}
public enum NoriMode
{
None,
Tengoku,
Mania,
ManiaHorizontal,
}
public static bool IsComboEnable = true; //only stops Out combo inputs, this basically makes combo contextual
public bool IsNoriActive { get { return Nori.MaxNori > 0; } }
public float NoriPerformance { get { if (IsNoriActive) return Nori.Nori / Nori.MaxNori; else return 1f; } }
public Color[] LightBulbColors;
public Color[] BackgroundColors;
public Color[] ShadowColors;
//camera positions (normal, special)
[Header("Camera Positions")]
public Transform[] CameraPosition;
Vector3 cameraPosition;
static double startCamSpecial = double.MinValue;
static double wantsReturn = double.MinValue;
static float cameraReturnLength = 0f;
static CameraAngle cameraAngle = CameraAngle.Normal;
//pot trajectory stuff
[Header("References")]
public Transform ItemHolder;
public GameObject Item;
public KarateManJoe Joe;
public GameObject NoriGO;
public KarateManNoriController Nori;
[Header("Colour Map")]
public Material MappingMaterial;
public static Color BodyColor = Color.white;
public static Color HighlightColor = new Color(0.81f,0.81f,0.81f,1);
public static Color ItemColor = Color.white;
[Header("Word")]
public Animator Word;
static double wordClearTime = double.MinValue;
const float hitVoiceOffset = 0.042f;
[Header("Backgrounds")]
// new bg fading
private double colorStartBeat = -1;
private float colorLength = 0f;
private Color colorStart = new Color(0.985f, 0.79f, 0.243f);
private Color colorEnd = new Color(0.985f, 0.79f, 0.243f);
private Util.EasingFunction.Ease colorEase;
static int bgType = (int) BackgroundType.Yellow;
public static int currentBgEffect = (int) BackgroundFXType.None;
public SpriteRenderer BGPlane;
public GameObject BGEffect;
Animator bgEffectAnimator;
SpriteRenderer bgEffectSpriteRenderer;
static int textureType = (int) BackgroundTextureType.Plain;
static int textureFilterType = (int) ShadowType.Tinted;
static Color filterColour = Color.white;
static Color filterColourNext = Color.white;
public GameObject BGGradient;
SpriteRenderer bgGradientRenderer;
public GameObject BGBlood;
SpriteRenderer bgBloodRenderer;
public GameObject BGRadial;
SpriteRenderer bgRadialRenderer;
SpriteRenderer[] bgFxRenderers;
[Header("Shadows")]
static int currentShadowType = (int) ShadowType.Tinted;
static Color customShadowColour = Color.white;
static Color oldShadowColour;
[Header("Particles")]
//wind
public WindZone Wind;
//snow
public ParticleSystem SnowEffect;
public GameObject SnowEffectGO;
//fire
public ParticleSystem FireEffect;
public GameObject FireEffectGO;
//rain
public ParticleSystem RainEffect;
public GameObject RainEffectGO;
[Header("Unloaded Game Calls")]
public List<RiqEntity> voiceEntities = new();
public List<RiqEntity> hitVoiceEntities = new();
private void Awake()
{
instance = this;
KarateManPot.ResetLastCombo();
cameraPosition = CameraPosition[0].position;
bgGradientRenderer = BGGradient.GetComponent<SpriteRenderer>();
bgBloodRenderer = BGBlood.GetComponent<SpriteRenderer>();
bgRadialRenderer = BGRadial.GetComponent<SpriteRenderer>();
}
public override void OnGameSwitch(double beat)
{
// queued objects
if (queuedObjects.Count > 0) {
foreach (var qObj in queuedObjects) { CreateItem(qObj.beat, qObj.type, qObj.expression); }
queuedObjects.Clear();
}
if (queuedBulbs.Count > 0) {
foreach (var qObj in queuedBulbs) { CreateBulbSpecial(qObj.beat, qObj.type, qObj.color, qObj.expression); }
queuedBulbs.Clear();
}
if (queuedKicks.Count > 0) {
foreach (var qObj in queuedKicks) { Kick(qObj.beat, qObj.ball, qObj.expression, qObj.cutOut, qObj.noVoice); }
queuedKicks.Clear();
}
if (queuedCombos.Count > 0) {
foreach (var qObj in queuedCombos) { Combo(qObj.beat, qObj.expression, qObj.cutOut, qObj.noVoice); }
queuedCombos.Clear();
}
List<RiqEntity> prevEntities = GameManager.instance.Beatmap.Entities.FindAll(c => c.datamodel.Split(0) == "karateman");
// init colors
RiqEntity bg = prevEntities.FindLast(c => c.beat < beat && c.datamodel.Split(1) == "set background effects");
RiqEntity obj = prevEntities.FindLast(c => c.beat < beat && c.datamodel.Split(1) == "set object colors");
if (bg != null) {
} else {
}
// if (bg != null) {
// SetBgAndShadowCol(bg.beat, 0, bg["type"], bg["type2"], bg["colorA"], bg["colorB"], bg["type3"] == (int)BackgroundFXType.Fade ? 0 : bg["type3"]);
// SetBgTexture(bg["type4"], bg["type5"], bg["colorC"], bg["colorD"]);
// } else {
// SetBgAndShadowCol(0, 0, 0, 0, new Color(), new Color(), 0);
// SetBgTexture(0, 0, new Color(), new Color());
// }
if (obj != null) {
UpdateMaterialColour(obj["colorA"], obj["colorB"], obj["colorC"]);
} else {
UpdateMaterialColour(Color.white, new Color(0.81f, 0.81f, 0.81f), Color.white);
}
// init modifier(s)
RiqEntity bop = prevEntities.FindLast(c => c.beat < beat && c.datamodel.Split(1) == "bop");
if (bop != null) ToggleBop(0, 0, false, bop["toggle"]);
else ToggleBop(0, 0, false, true);
// get all entities to later check against eachother to cut out voices
voiceEntities = prevEntities.FindAll(c => c.beat > beat && (c.datamodel.Split(1) is "kick" or "combo"));
for (int i = 0; i < voiceEntities.Count; i++) {
Debug.Log("voice entity " + (i+1) + " : " + voiceEntities[i].beat);
}
hitVoiceEntities = prevEntities.FindAll(c => c.beat > beat && (c.datamodel.Split(1) is "warnings" && c["whichWarning"] <= (int)HitThree.HitFour));
for (int i = 0; i < hitVoiceEntities.Count; i++) {
Debug.Log("hitVoice entity " + (i+1) + " : " + hitVoiceEntities[i].beat);
}
}
public override void OnPlay(double beat)
{
OnGameSwitch(beat);
}
private void Start()
{
var cond = Conductor.instance;
GameCamera.additionalPosition = cameraPosition - GameCamera.defaultPosition;
bgEffectAnimator = BGEffect.GetComponent<Animator>();
bgEffectSpriteRenderer = BGEffect.GetComponent<SpriteRenderer>();
bgGradientRenderer = BGGradient.GetComponent<SpriteRenderer>();
bgBloodRenderer = BGBlood.GetComponent<SpriteRenderer>();
bgRadialRenderer = BGRadial.GetComponent<SpriteRenderer>();
}
private void Update()
{
var cond = Conductor.instance;
switch (currentBgEffect)
{
case (int) BackgroundFXType.Sunburst:
bgEffectAnimator.DoNormalizedAnimation("Sunburst", (cond.songPositionInBeats*0.5f) % 1f);
break;
case (int) BackgroundFXType.Rings:
bgEffectAnimator.DoNormalizedAnimation("Rings", (cond.songPositionInBeats*0.5f) % 1f);
break;
default:
bgEffectAnimator.Play("NoPose", -1, 0);
break;
}
if (cond.songPositionInBeatsAsDouble >= wordClearTime)
{
Word.Play("NoPose");
}
if (cond.songPositionInBeatsAsDouble >= startCamSpecial && cond.songPositionInBeatsAsDouble <= wantsReturn)
{
float camX = 0f;
float camY = 0f;
float camZ = 0f;
if (cond.songPositionInBeatsAsDouble <= startCamSpecial + cameraReturnLength)
{
float prog = cond.GetPositionFromBeat(startCamSpecial, cameraReturnLength);
camX = Util.EasingFunction.EaseOutCubic(CameraPosition[0].position.x, CameraPosition[1].position.x, prog);
camY = Util.EasingFunction.EaseOutCubic(CameraPosition[0].position.y, CameraPosition[1].position.y, prog);
camZ = Util.EasingFunction.EaseOutCubic(CameraPosition[0].position.z, CameraPosition[1].position.z, prog);
cameraPosition = new Vector3(camX, camY, camZ);
}
else if (cond.songPositionInBeatsAsDouble >= wantsReturn - cameraReturnLength)
{
float prog = cond.GetPositionFromBeat(wantsReturn - cameraReturnLength, cameraReturnLength);
camX = Util.EasingFunction.EaseOutQuad(CameraPosition[1].position.x, CameraPosition[0].position.x, prog);
camY = Util.EasingFunction.EaseOutQuad(CameraPosition[1].position.y, CameraPosition[0].position.y, prog);
camZ = Util.EasingFunction.EaseOutQuad(CameraPosition[1].position.z, CameraPosition[0].position.z, prog);
cameraPosition = new Vector3(camX, camY, camZ);
}
else
{
cameraPosition = CameraPosition[1].position;
}
}
else
{
if (cameraAngle == CameraAngle.Special)
cameraAngle = CameraAngle.Normal;
cameraPosition = CameraPosition[0].position;
}
BackgroundColorUpdate();
GameCamera.additionalPosition = cameraPosition - GameCamera.defaultPosition;
BGEffect.transform.position = new Vector3(GameCamera.instance.transform.position.x, GameCamera.instance.transform.position.y, 0);
}
private void OnDestroy()
{
if (!Conductor.instance.NotStopped()) {
if (queuedObjects.Count > 0) queuedObjects.Clear();
if (queuedBulbs.Count > 0) queuedBulbs.Clear();
if (queuedKicks.Count > 0) queuedKicks.Clear();
if (queuedCombos.Count > 0) queuedCombos.Clear();
}
}
static List<RiqEntity> allHits = new List<RiqEntity>();
static List<RiqEntity> allEnds = new List<RiqEntity>();
public static int CountHitsToEnd(double fromBeat)
{
allHits = EventCaller.GetAllInGameManagerList("karateman", new string[] { "hit", "bulb", "kick", "combo" });
allEnds = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame", "end" });
allHits.Sort((x, y) => x.beat.CompareTo(y.beat));
allEnds.Sort((x, y) => x.beat.CompareTo(y.beat));
double endBeat = double.MaxValue;
//get the beat of the closest end event
foreach (var end in allEnds)
{
if (end.beat > fromBeat)
{
endBeat = end.beat;
break;
}
}
//count each hit event beginning from our current beat to the beat of the closest game switch or end
int count = 0;
string type;
for (int i = 0; i < allHits.Count; i++)
{
var h = allHits[i];
if (h.beat >= fromBeat)
{
if (h.beat < endBeat)
{
//kicks and combos count for 2 hits
type = (h.datamodel.Split('/'))[1];
count += (type is "kick" or "combo" ? 2 : 1);
}
else
break;
}
}
return count;
}
public static void DoSpecialCamera(double beat, float length, bool returns)
{
if (cameraAngle == CameraAngle.Normal)
{
startCamSpecial = beat;
cameraAngle = CameraAngle.Special;
}
wantsReturn = returns ? beat + length - 0.001f : double.MaxValue;
cameraReturnLength = Mathf.Min(2f, length*0.5f);
}
public void DoWord(double beat, double length, int type, bool customLength, bool doSound = true)
{
Word.Play(DoWordSound(beat, length, type, customLength, doSound));
}
public static string DoWordSound(double beat, double length, int type, bool customLength, bool doSound = true)
{
string word = "NoPose";
double clear = 0f;
if (type <= (int)HitThree.HitFour) {
string number = type.ToString().Substring(3);
number = char.ToLower(number[0]).ToString() + number.Substring(1);
MultiSound.Play(new MultiSound.Sound[] {
new MultiSound.Sound($"karateman/{(type == (int)HitThree.HitThreeAlt ? "hitAlt" : "hit")}", beat + 0.5f, offset: hitVoiceOffset),
new MultiSound.Sound($"karateman/{number}", beat + 1f),
}, forcePlay: true);
clear = beat + 4f;
}
switch (type)
{
case (int) HitThree.HitOne: // lol
word = "Word06";
clear = beat + 4f;
if (doSound)
MultiSound.Play(new MultiSound.Sound[] {
new MultiSound.Sound("karateman/hit", beat + 0.5f, offset: hitVoiceOffset),
new MultiSound.Sound("karateman/one", beat + 1f),
}, forcePlay: true);
break;
case (int) HitThree.HitTwo:
word = "Word02";
clear = beat + 4f;
if (doSound)
MultiSound.Play(new MultiSound.Sound[] {
new MultiSound.Sound("karateman/hit", beat + 0.5f, offset: hitVoiceOffset),
new MultiSound.Sound("karateman/two", beat + 1f),
}, forcePlay: true);
break;
case (int) HitThree.HitThree:
word = "Word03";
clear = beat + 4f;
if (doSound)
MultiSound.Play(new MultiSound.Sound[] {
new MultiSound.Sound("karateman/hit", beat + 0.5f, offset: hitVoiceOffset),
new MultiSound.Sound("karateman/three", beat + 1f),
}, forcePlay: true);
break;
case (int) HitThree.HitThreeAlt:
word = "Word03";
clear = beat + 4f;
if (doSound)
MultiSound.Play(new MultiSound.Sound[] {
new MultiSound.Sound("karateman/hitAlt", beat + 0.5f, offset: hitVoiceOffset),
new MultiSound.Sound("karateman/threeAlt", beat + 1f),
}, forcePlay: true);
break;
case (int) HitThree.HitFour:
word = "Word04";
clear = beat + 4f;
if (doSound)
MultiSound.Play(new MultiSound.Sound[]
{
new MultiSound.Sound("karateman/hit", beat + 0.5f, offset: hitVoiceOffset),
new MultiSound.Sound("karateman/four", beat + 1f),
}, forcePlay: true);
break;
case (int) HitThree.Grr:
word = "Word01";
clear = beat + 1f;
break;
case (int) HitThree.Warning:
word = "Word05";
clear = beat + 1f;
break;
case (int) HitThree.Combo:
word = "Word00";
clear = beat + 3f;
break;
}
if (Conductor.instance.songPositionInBeatsAsDouble <= clear && Conductor.instance.songPositionInBeatsAsDouble >= beat)
{
wordClearTime = customLength ? (beat + length) : clear;
}
return word;
}
public static void CreateItemSFX(double beat, int type, bool muteSound = false, bool isBulb = false)
{
if (!muteSound) SoundByte.PlayOneShotGame($"karateman/{(beat % 1.0 == 0.5 ? "offbeatObject" : "object")}Out", forcePlay: true);
}
public static void QueueItem(double beat, int type, int expression)
{
queuedObjects.Add(new QueuedObject() {
beat = beat,
type = type,
expression = expression,
});
}
public void CreateItem(double beat, int type, int expression)
{
switch (type)
{
case (int) HitType.Pot:
CreateItemInstance(beat, "Item00", expression);
break;
case (int) HitType.Lightbulb:
var mobj = CreateItemInstance(beat, "Item01", expression, KarateManPot.ItemType.Bulb);
mobj.GetComponent<KarateManPot>().SetBulbColor(LightBulbColors[0]);
break;
case (int) HitType.Rock:
CreateItemInstance(beat, "Item02", expression, KarateManPot.ItemType.Rock);
break;
case (int) HitType.Ball:
CreateItemInstance(beat, "Item03", expression, KarateManPot.ItemType.Ball);
break;
case (int) HitType.CookingPot:
CreateItemInstance(beat, "Item06", expression, KarateManPot.ItemType.Cooking);
break;
case (int) HitType.Alien:
CreateItemInstance(beat, "Item07", expression, KarateManPot.ItemType.Alien);
break;
case (int) HitType.Bomb:
CreateItemInstance(beat, "Item04", expression, KarateManPot.ItemType.Bomb);
break;
case (int) HitType.TacoBell:
CreateItemInstance(beat, "Item99", expression, KarateManPot.ItemType.TacoBell);
break;
default:
CreateItemInstance(beat, "Item00", expression);
break;
}
}
public static void QueueBulb(double beat, int type, Color color, int expression)
{
queuedBulbs.Add(new QueuedObject() {
beat = beat,
type = type,
color = color,
expression = expression,
});
}
public void CreateBulbSpecial(double beat, int type, Color c, int expression)
{
var mobj = CreateItemInstance(beat, "Item01", expression, KarateManPot.ItemType.Bulb);
if (type == (int) LightBulbType.Custom) {
mobj.GetComponent<KarateManPot>().SetBulbColor(c);
} else {
mobj.GetComponent<KarateManPot>().SetBulbColor(LightBulbColors[type]);
}
}
public static void ComboSFX()
{
SoundByte.PlayOneShotGame("karateman/barrelOutCombos", forcePlay: true);
}
public static void QueueCombo(double beat, int expression, bool cutOut, bool noVoice)
{
queuedCombos.Add(new QueuedSpecial() {
beat = beat,
expression = expression,
cutOut = cutOut,
noVoice = noVoice
});
}
public void Combo(double beat, int expression, bool cutOut, bool noVoice)
{
int comboId = KarateManPot.GetNewCombo();
BeatAction.New(gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat, delegate { CreateItemInstance(beat, "Item00", 0, KarateManPot.ItemType.ComboPot1, comboId); }),
new BeatAction.Action(beat + 0.25f, delegate { CreateItemInstance(beat + 0.25f, "Item00", 0, KarateManPot.ItemType.ComboPot2, comboId); }),
new BeatAction.Action(beat + 0.5f, delegate { CreateItemInstance(beat + 0.5f, "Item00", 0, KarateManPot.ItemType.ComboPot3, comboId); }),
new BeatAction.Action(beat + 0.75f, delegate { CreateItemInstance(beat + 0.75f, "Item00", 0, KarateManPot.ItemType.ComboPot4, comboId); }),
new BeatAction.Action(beat + 1f, delegate { CreateItemInstance(beat + 1f, "Item00", 0, KarateManPot.ItemType.ComboPot5, comboId); }),
new BeatAction.Action(beat + 1.5f, delegate { CreateItemInstance(beat + 1.5f, "Item05", expression, KarateManPot.ItemType.ComboBarrel, comboId); }),
});
if (noVoice) return;
List<MultiSound.Sound> sounds = new() {
new MultiSound.Sound("karateman/punchy1", beat + 1f),
new MultiSound.Sound("karateman/punchy2", beat + 1.25f),
new MultiSound.Sound("karateman/punchy3", beat + 1.5f),
new MultiSound.Sound("karateman/punchy4", beat + 1.75f),
new MultiSound.Sound("karateman/ko", beat + 2f),
new MultiSound.Sound("karateman/pow", beat + 2.5f)
};
if (voiceEntities.Count > 0) {
RiqEntity firstVoice = voiceEntities.Find(x => x.beat >= beat + 1);
RiqEntity firstHitVoice = hitVoiceEntities.Find(x => x.beat >= beat + 1);
if (firstVoice != null) sounds.RemoveAll(x => x.beat > firstVoice.beat);
if (firstHitVoice != null) sounds.RemoveAll(x => x.beat > firstHitVoice.beat - 0.5);
}
MultiSound.Play(sounds.ToArray(), forcePlay: true);
}
public static void KickSFX()
{
SoundByte.PlayOneShotGame("karateman/barrelOutKicks", forcePlay: true);
}
public static void QueueKick(double beat, bool ball, int expression, bool cutOut, bool noVoice)
{
queuedKicks.Add(new QueuedSpecial() {
beat = beat,
expression = expression,
cutOut = cutOut,
noVoice = noVoice,
ball = ball,
});
}
public void Kick(double beat, bool ball, int expression, bool cutOut, bool noVoice)
{
CreateItemInstance(beat, "Item05", expression, KarateManPot.ItemType.KickBarrel, content: ball);
if (!noVoice) {
MultiSound.Play(new MultiSound.Sound[] {
new MultiSound.Sound("karateman/punchKick1", beat + 1f),
new MultiSound.Sound("karateman/punchKick2", beat + 1.5f),
new MultiSound.Sound("karateman/punchKick3", beat + 1.75f),
new MultiSound.Sound("karateman/punchKick4", beat + 2.5f),
}, forcePlay: true);
}
}
public GameObject CreateItemInstance(double beat, string awakeAnim, int successExpression, KarateManPot.ItemType type = KarateManPot.ItemType.Pot, int comboId = -1, bool content = false)
{
GameObject mobj = GameObject.Instantiate(Item, ItemHolder);
KarateManPot mobjDat = mobj.GetComponent<KarateManPot>();
mobjDat.type = type;
mobjDat.startBeat = beat;
mobjDat.awakeAnim = awakeAnim;
mobjDat.comboId = comboId;
mobjDat.OnHitExpression = successExpression;
mobjDat.KickBarrelContent = content;
mobj.SetActive(true);
return mobj;
}
public void BackgroundColor(double beat, float length, int presetBG, int shadowType, int fxType, Color colorStartSet, Color colorEndSet, int ease)
{
//////////////////////////////////////////
// preset = BackgroundType //
// shadow = ShadowType //
// fxType = BackgroundFXType //
// textureType = BackgroundTextureType //
//////////////////////////////////////////
if (presetBG != (int)BackgroundType.Custom) {
colorEndSet = BackgroundColors[presetBG];
}
colorStartBeat = beat;
colorLength = length;
colorStart = colorStartSet;
colorEnd = colorEndSet;
colorEase = (Util.EasingFunction.Ease)ease;
}
public void SetBgTexture(int type, int filterType, Color colorStartSet, Color colorEndSet)
{
textureType = type;
textureFilterType = filterType;
if (textureFilterType == (int) ShadowType.Tinted)
filterColour = Color.LerpUnclamped(colorStartSet, colorEndSet, 0.45f);
else
{
filterColour = colorStartSet;
filterColourNext = colorEndSet;
}
switch (textureType)
{
case (int) BackgroundTextureType.Blood:
BGBlood.SetActive(true);
BGGradient.SetActive(false);
BGRadial.SetActive(false);
break;
case (int) BackgroundTextureType.Gradient:
BGGradient.SetActive(true);
BGBlood.SetActive(false);
BGRadial.SetActive(false);
break;
case (int) BackgroundTextureType.Radial:
BGRadial.SetActive(true);
BGBlood.SetActive(false);
BGGradient.SetActive(false);
break;
default:
BGGradient.SetActive(false);
BGBlood.SetActive(false);
BGRadial.SetActive(false);
break;
}
BackgroundColorUpdate();
}
private void BackgroundColorUpdate()
{
float normalizedBeat = Mathf.Clamp01(Conductor.instance.GetPositionFromBeat(colorStartBeat, colorLength));
var func = Util.EasingFunction.GetEasingFunction(colorEase);
float newR = func(colorStart.r, colorEnd.r, normalizedBeat);
float newG = func(colorStart.g, colorEnd.g, normalizedBeat);
float newB = func(colorStart.b, colorEnd.b, normalizedBeat);
BGPlane.color = new Color(newR, newG, newB);
// bgGradientRenderer.color = filterCol;
// bgBloodRenderer.color = filterCol;
// bgRadialRenderer.color = filterCol;
}
// public void SetBgAndShadowCol(double beat, float length, int newBgType, int shadowType, Color a, Color b, int fx)
// {
// SetBgFx(fx, beat, length);
// UpdateShadowColour(shadowType, b);
// bgType = newBgType;
// if (bgType == (int) BackgroundType.Custom)
// bgColour = a;
// else
// bgColour = BackgroundColors[newBgType];
// BGPlane.color = bgColour;
// //😢
// if (fx != (int) BackgroundFXType.Fade)
// {
// bgColourLast = bgColour;
// oldShadowColour = GetShadowColor(true);
// }
// if (textureFilterType == (int) ShadowType.Tinted)
// filterColour = Color.LerpUnclamped(bgColour, ShadowBlendColor, 0.45f);
// }
// public void SetBgFx(int fx, double beat, float length)
// {
// switch (fx)
// {
// case (int) BackgroundFXType.Fade:
// bgColourLast = bgColour;
// bgFadeTime = beat;
// bgFadeDuration = length;
// break;
// default:
// currentBgEffect = fx;
// break;
// }
// }
public void SetGameplayMods(double beat, int mode, bool combo)
{
NoriGO.SetActive(true);
Nori.SetNoriMode(beat, mode);
IsComboEnable = combo;
}
public static Color ShadowBlendColor = new Color(195 / 255f, 48 / 255f, 2 / 255f);
// public Color GetShadowColor(bool next = false)
// {
// Color lastCol, nextCol;
// lastCol = oldShadowColour;
// if (currentShadowType == (int) ShadowType.Custom)
// nextCol = customShadowColour;
// else if (bgType < (int) BackgroundType.Custom)
// nextCol = ShadowColors[bgType];
// else
// nextCol = Color.LerpUnclamped(bgColour, ShadowBlendColor, 0.45f);
// float fadeProg = Conductor.instance.GetPositionFromBeat(bgFadeTime, bgFadeDuration);
// if (fadeProg <= 1f && fadeProg >= 0)
// {
// return Color.LerpUnclamped(lastCol, nextCol, fadeProg);
// }
// return next ? nextCol : lastCol;
// }
// public void UpdateShadowColour(int type, Color colour)
// {
// if (currentShadowType == (int) ShadowType.Custom)
// oldShadowColour = customShadowColour;
// else if (bgType < (int) BackgroundType.Custom)
// oldShadowColour = ShadowColors[bgType];
// else
// oldShadowColour = Color.LerpUnclamped(bgColour, ShadowBlendColor, 0.45f);
// currentShadowType = type;
// customShadowColour = colour;
// }
public static void UpdateMaterialColour(Color mainCol, Color highlightCol, Color objectCol)
{
BodyColor = mainCol;
HighlightColor = highlightCol;
ItemColor = objectCol;
}
public void SetParticleEffect(double beat, int type, float windStrength, float particleStrength)
{
ParticleSystem.EmissionModule emm;
switch (type)
{
case (int) ParticleType.Snow:
SnowEffectGO.SetActive(true);
SnowEffect.Play();
emm = SnowEffect.emission;
emm.rateOverTime = particleStrength * 6f;
break;
case (int) ParticleType.Fire:
FireEffectGO.SetActive(true);
FireEffect.Play();
emm = FireEffect.emission;
emm.rateOverTime = particleStrength * 6f;
break;
case (int) ParticleType.Rain:
RainEffectGO.SetActive(true);
RainEffect.Play();
emm = RainEffect.emission;
emm.rateOverTime = particleStrength * 32f;
break;
default:
SnowEffect.Stop();
FireEffect.Stop();
RainEffect.Stop();
break;
}
Wind.windMain = windStrength;
}
public void ToggleBop(double beat, float length, bool toggle, bool autoBop)
{
if (autoBop)
Joe.bop.length = float.MaxValue;
else
Joe.bop.length = 0;
if (toggle)
{
for (int i = 0; i < length; i++)
{
BeatAction.New(instance.gameObject, new List<BeatAction.Action>()
{
new BeatAction.Action(beat + i, delegate
{
Joe.Bop();
})
});
}
}
}
public void Prepare(double beat, float length)
{
Joe.Prepare(beat, length);
}
public void SetFaceExpression(int face)
{
Joe.SetFaceExpression(face);
}
}
}