Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Ne_Eo
2024-08-27 03:48:18 +02:00
27 changed files with 220 additions and 80 deletions
+6
View File
@@ -9,4 +9,10 @@
<anim name="singLEFTmiss" anim="BF NOTE LEFT MISS" fps="24" loop="false" x="12" y="24"/>
<anim name="singRIGHTmiss" anim="BF NOTE RIGHT MISS" fps="24" loop="false" x="-30" y="21"/>
<anim name="singDOWNmiss" anim="BF NOTE DOWN MISS" fps="24" loop="false" x="-11" y="-19"/>
<!-- funny loop -->
<anim name="idle-loop" anim="BF idle dance" fps="24" loop="true" x="-5" y="0" indices="10,11,12,13"/>
<anim name="singUP-loop" anim="BF NOTE UP0" fps="24" loop="true" x="-29" y="27" indices="11,12,13,14"/>
<anim name="singLEFT-loop" anim="BF NOTE LEFT0" fps="24" loop="true" x="12" y="-6" indices="12,13,14,15"/>
<anim name="singRIGHT-loop" anim="BF NOTE RIGHT0" fps="24" loop="true" x="-38" y="-7" indices="58,59,60,61"/>
<anim name="singDOWN-loop" anim="BF NOTE DOWN0" fps="24" loop="true" x="-10" y="-50" indices="26,27,28,29"/>
</character>
+5
View File
@@ -5,4 +5,9 @@
<anim name="singLEFT" anim="dad sing note right" fps="24" loop="false" x="-2" y="10"/>
<anim name="singRIGHT" anim="Dad Sing Note LEFT" fps="24" loop="false" x="-5" y="27"/>
<anim name="singDOWN" anim="Dad Sing Note DOWN" fps="24" loop="false" x="0" y="-30"/>
<!-- funny loop -->
<anim name="idle-loop" anim="Dad idle dance" fps="24" loop="true" x="0" y="0" indices="10,11,12,12"/>
<anim name="singUP-loop" anim="Dad Sing note UP" fps="24" loop="true" x="-6" y="50" indices="56,57,58,59"/>
<anim name="singLEFT-loop" anim="dad sing note right" fps="24" loop="true" x="-10" y="10" indices="12,13,14,15"/>
<anim name="singRIGHT-loop" anim="Dad Sing Note LEFT" fps="24" loop="true" x="0" y="27" indices="15,16,17,18"/>
</character>
+5
View File
@@ -5,4 +5,9 @@
<anim name="singLEFT" anim="dad sing note right" fps="24" loop="false" x="-10" y="10"/>
<anim name="singRIGHT" anim="Dad Sing Note LEFT" fps="24" loop="false" x="0" y="27"/>
<anim name="singDOWN" anim="Dad Sing Note DOWN" fps="24" loop="false" x="0" y="-30"/>
<!-- funny loop -->
<anim name="idle-loop" anim="Dad idle dance" fps="24" loop="true" x="0" y="0" indices="10,11,12,12"/>
<anim name="singUP-loop" anim="Dad Sing note UP" fps="24" loop="true" x="-6" y="50" indices="56,57,58,59"/>
<anim name="singLEFT-loop" anim="dad sing note right" fps="24" loop="true" x="-10" y="10" indices="12,13,14,15"/>
<anim name="singRIGHT-loop" anim="Dad Sing Note LEFT" fps="24" loop="true" x="0" y="27" indices="15,16,17,18"/>
</character>
+6
View File
@@ -7,4 +7,10 @@
<!-- ANIMATION IS CALLED MOM LEFT POSE BUT ITS FOR THE RIGHT -->
<!-- CUZ DAVE IS DUMB! -->
<anim name="singRIGHT" anim="Mom Pose Left" fps="24" loop="false" x="10" y="-60"/>
<!-- funny loop -->
<anim name="idle-loop" anim="Mom Idle" fps="24" loop="true" indices="10,11,12,13"/>
<anim name="singUP-loop" anim="Mom Up Pose" fps="24" loop="true" x="14" y="71" indices="11,12,13,14"/>
<anim name="singDOWN-loop" anim="MOM DOWN POSE" fps="24" loop="true" x="20" y="-160" indices="11,12,13,14"/>
<anim name="singLEFT-loop" anim="Mom Left Pose" fps="24" loop="true" x="250" y="-23" indices="6,7,8,9"/>
<anim name="singRIGHT-loop" anim="Mom Pose Left" fps="24" loop="true" x="10" y="-60" indices="6,7,8,9"/>
</character>
+6
View File
@@ -7,4 +7,10 @@
<!-- ANIMATION IS CALLED MOM LEFT POSE BUT ITS FOR THE RIGHT -->
<!-- CUZ DAVE IS DUMB! -->
<anim name="singRIGHT" anim="Mom Pose Left" fps="24" loop="false" x="10" y="-60"/>
<!-- funny loop -->
<anim name="idle-loop" anim="Mom Idle" fps="24" loop="true" indices="10,11,12,13"/>
<anim name="singUP-loop" anim="Mom Up Pose" fps="24" loop="true" x="14" y="71" indices="11,12,13,14"/>
<anim name="singDOWN-loop" anim="MOM DOWN POSE" fps="24" loop="true" x="20" y="-160" indices="9,10,11,12"/>
<anim name="singLEFT-loop" anim="Mom Left Pose" fps="24" loop="true" x="250" y="-23" indices="6,7,8,9"/>
<anim name="singRIGHT-loop" anim="Mom Pose Left" fps="24" loop="true" x="10" y="-60" indices="6,7,8,9"/>
</character>
+1 -1
View File
@@ -3,5 +3,5 @@
<menu name="Mod Credits" desc="Modify mod credits here">
<!-- \/ You can also set the portrait shader as false as you can see below in the github one -->
<credit name="Credit Example" desc="Click me to know more about me!" icon="credit icon example" size="130" url="https://youtu.be/fugtxz1znVw"/>
<github user="NexIsDumb" customName="Nex is Dumb" desc="The bitch who made these credits menus" size="100" portrait="false"/>
<github user="NexIsDumb" customName="Nex is Dumb" desc="The bitch who made these credits menus" size="100" portrait="false" color="#808080"/>
</menu>
+1 -1
View File
@@ -1,4 +1,4 @@
story mode
freeplay
options
donate
credits
+3 -2
View File
@@ -15,8 +15,9 @@
<SubTexture name="MOM DOWN POSE0010" x="1246" y="0" width="403" height="600" frameX="0" frameY="-13" frameWidth="414" frameHeight="613"/>
<SubTexture name="MOM DOWN POSE0011" x="1246" y="0" width="403" height="600" frameX="0" frameY="-13" frameWidth="414" frameHeight="613"/>
<SubTexture name="MOM DOWN POSE0012" x="833" y="0" width="403" height="600" frameX="0" frameY="-13" frameWidth="414" frameHeight="613"/>
<SubTexture name="MOM DOWN POSE0013" x="1659" y="0" width="403" height="600" frameX="0" frameY="-13" frameWidth="414" frameHeight="613"/>
<SubTexture name="MOM DOWN POSE0014" x="1659" y="0" width="403" height="600" frameX="0" frameY="-13" frameWidth="414" frameHeight="613"/>
<!-- commented out because she has no face -->
<!-- <SubTexture name="MOM DOWN POSE0013" x="1659" y="0" width="403" height="600" frameX="0" frameY="-13" frameWidth="414" frameHeight="613"/>
<SubTexture name="MOM DOWN POSE0014" x="1659" y="0" width="403" height="600" frameX="0" frameY="-13" frameWidth="414" frameHeight="613"/> -->
<SubTexture name="Mom Idle0000" x="2072" y="0" width="386" height="826" frameX="-4" frameY="-2" frameWidth="390" frameHeight="829"/>
<SubTexture name="Mom Idle0001" x="2072" y="0" width="386" height="826" frameX="-4" frameY="-2" frameWidth="390" frameHeight="829"/>
<SubTexture name="Mom Idle0002" x="2468" y="0" width="386" height="815" frameX="-4" frameY="-14" frameWidth="390" frameHeight="829"/>
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Created with Funkin Packer v0.1.3 https://neeeoo.github.io/funkin-packer/
-->
<TextureAtlas imagePath="credits.png" width="522" height="905">
<SubTexture name="credits white0001" x="1" y="1" width="520" height="172" frameX="-2" frameY="20" frameWidth="522" frameHeight="172"/>
<SubTexture name="credits white0002" x="1" y="176" width="520" height="172" frameX="-0" frameY="20" frameWidth="522" frameHeight="172"/>
<SubTexture name="credits white0003" x="1" y="351" width="519" height="172" frameX="-2" frameY="20" frameWidth="522" frameHeight="172"/>
<SubTexture name="credits basic0001" x="1" y="526" width="439" height="124" frameX="-0" frameY="5" frameWidth="439" frameHeight="125"/>
<SubTexture name="credits basic0002" x="1" y="526" width="439" height="124" frameX="-0" frameY="5" frameWidth="439" frameHeight="125"/>
<SubTexture name="credits basic0003" x="1" y="526" width="439" height="124" frameX="-0" frameY="5" frameWidth="439" frameHeight="125"/>
<SubTexture name="credits basic0004" x="1" y="653" width="439" height="124" frameX="-0" frameY="5" frameWidth="439" frameHeight="125"/>
<SubTexture name="credits basic0005" x="1" y="653" width="439" height="124" frameX="-0" frameY="5" frameWidth="439" frameHeight="125"/>
<SubTexture name="credits basic0006" x="1" y="653" width="439" height="124" frameX="-0" frameY="5" frameWidth="439" frameHeight="125"/>
<SubTexture name="credits basic0007" x="1" y="780" width="439" height="124" frameX="-0" frameY="5" frameWidth="439" frameHeight="125"/>
<SubTexture name="credits basic0008" x="1" y="780" width="439" height="124" frameX="-0" frameY="5" frameWidth="439" frameHeight="125"/>
<SubTexture name="credits basic0009" x="1" y="780" width="439" height="124" frameX="-0" frameY="5" frameWidth="439" frameHeight="125"/>
</TextureAtlas>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 29 KiB

+17 -16
View File
@@ -1,17 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<TextureAtlas imagePath="freeplay.png">
<!-- Created with Adobe Animate version 21.0.1.37179 and edited by Nex_isDumb -->
<!-- http://www.adobe.com/products/animate.html -->
<SubTexture name="freeplay basic0000" x="2" y="2" width="484" height="122" pivotX="7.65" pivotY="10.55"/>
<SubTexture name="freeplay basic0001" x="2" y="2" width="484" height="122"/>
<SubTexture name="freeplay basic0002" x="2" y="2" width="484" height="122"/>
<SubTexture name="freeplay basic0003" x="2" y="126" width="484" height="122"/>
<SubTexture name="freeplay basic0004" x="2" y="126" width="484" height="122"/>
<SubTexture name="freeplay basic0005" x="2" y="126" width="484" height="122"/>
<SubTexture name="freeplay basic0006" x="2" y="250" width="484" height="122"/>
<SubTexture name="freeplay basic0007" x="2" y="250" width="484" height="122"/>
<SubTexture name="freeplay basic0008" x="2" y="250" width="484" height="122"/>
<SubTexture name="freeplay white0000" x="2" y="374" width="627" height="169" pivotX="15" pivotY="17.15" frameX="0" frameY="20" frameWidth="635" frameHeight="174"/>
<SubTexture name="freeplay white0001" x="2" y="545" width="632" height="170" frameX="-3" frameY="19" frameWidth="635" frameHeight="174"/>
<SubTexture name="freeplay white0002" x="2" y="717" width="629" height="173" frameX="-4" frameY="19" frameWidth="635" frameHeight="174"/>
<?xml version="1.0" encoding="UTF-8"?>
<!--
Created with Funkin Packer v0.1.3 https://neeeoo.github.io/funkin-packer/
-->
<TextureAtlas imagePath="freeplay.png" width="634" height="894">
<SubTexture name="freeplay basic0000" x="1" y="521" width="484" height="122" frameX="-0" frameY="-0" frameWidth="484" frameHeight="122"/>
<SubTexture name="freeplay basic0001" x="1" y="521" width="484" height="122" frameX="-0" frameY="-0" frameWidth="484" frameHeight="122"/>
<SubTexture name="freeplay basic0002" x="1" y="521" width="484" height="122" frameX="-0" frameY="-0" frameWidth="484" frameHeight="122"/>
<SubTexture name="freeplay basic0003" x="1" y="646" width="484" height="122" frameX="-0" frameY="-0" frameWidth="484" frameHeight="122"/>
<SubTexture name="freeplay basic0004" x="1" y="646" width="484" height="122" frameX="-0" frameY="-0" frameWidth="484" frameHeight="122"/>
<SubTexture name="freeplay basic0005" x="1" y="646" width="484" height="122" frameX="-0" frameY="-0" frameWidth="484" frameHeight="122"/>
<SubTexture name="freeplay basic0006" x="1" y="771" width="484" height="122" frameX="-0" frameY="-0" frameWidth="484" frameHeight="122"/>
<SubTexture name="freeplay basic0007" x="1" y="771" width="484" height="122" frameX="-0" frameY="-0" frameWidth="484" frameHeight="122"/>
<SubTexture name="freeplay basic0008" x="1" y="771" width="484" height="122" frameX="-0" frameY="-0" frameWidth="484" frameHeight="122"/>
<SubTexture name="freeplay white0000" x="1" y="350" width="627" height="168" frameX="-0" frameY="20" frameWidth="635" frameHeight="174"/>
<SubTexture name="freeplay white0001" x="1" y="1" width="632" height="170" frameX="-3" frameY="19" frameWidth="635" frameHeight="174"/>
<SubTexture name="freeplay white0002" x="1" y="174" width="628" height="173" frameX="-4" frameY="19" frameWidth="635" frameHeight="174"/>
</TextureAtlas>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
+12
View File
@@ -94,6 +94,14 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
public override function update(elapsed:Float)
{
super.update(elapsed);
// hate how it looks like but hey at least its optimized and fast - Nex
if (!debugMode && isAnimFinished()) {
var name = getAnimName() + '-loop';
if (animation.exists(name))
playAnim(name, false, lastAnimContext);
}
if (animateAtlas != null)
animateAtlas.update(elapsed);
}
@@ -328,6 +336,10 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
return (animateAtlas != null) ? atlasPlayingAnim : animation.name;
}
public inline function isAnimReversed():Bool {
return animateAtlas != null ? animateAtlas.anim.reversed : animation.curAnim != null ? animation.curAnim.reversed : false;
}
public inline function removeAnimation(name:String) {
if (animateAtlas != null)
@:privateAccess animateAtlas.anim.animsMap.remove(name);
+85
View File
@@ -821,6 +821,91 @@ class CoolUtil
var file = new haxe.io.Path(file);
return file.file;
}
/**
* Converts a string of "1..3,5,7..9,8..5" into an array of numbers like [1,2,3,5,7,8,9,8,7,6,5]
* @param input String to parse
* @return Array of numbers
*/
public static function parseNumberRange(input:String):Array<Int> {
var result:Array<Int> = [];
var parts:Array<String> = input.split(",");
for (part in parts) {
part = part.trim();
var idx = part.indexOf("..");
if (idx != -1) {
var start = Std.parseInt(part.substring(0, idx).trim());
var end = Std.parseInt(part.substring(idx + 2).trim());
if(start == null || end == null) {
continue;
}
if (start < end) {
for (j in start...end + 1) {
result.push(j);
}
} else {
for (j in end...start + 1) {
result.push(start + end - j);
}
}
} else {
var num = Std.parseInt(part);
if (num != null) {
result.push(num);
}
}
}
return result;
}
/**
* Converts an array of numbers into a string of ranges.
* Example: [1,2,3,5,7,8,9,8,7,6,5] -> "1..3,5,7..9,8..5"
* @param numbers Array of numbers
* @return String representing the ranges
*/
public static function formatNumberRange(numbers:Array<Int>, seperator:String = ","):String {
if (numbers.length == 0) return "";
var result:Array<String> = [];
var i = 0;
while (i < numbers.length) {
var start = numbers[i];
var end = start;
var direction = 0; // 0: no sequence, 1: increasing, -1: decreasing
if (i + 1 < numbers.length) { // detect direction of sequence
if (numbers[i + 1] == end + 1) {
direction = 1;
} else if (numbers[i + 1] == end - 1) {
direction = -1;
}
}
if(direction != 0) {
while (i + 1 < numbers.length && (numbers[i + 1] == end + direction)) {
end = numbers[i + 1];
i++;
}
}
if (start == end) { // no direction
result.push('${start}');
} else if (start + direction == end) { // 1 step increment
result.push('${start},${end}');
} else { // store as range
result.push('${start}..${end}');
}
i++;
}
return result.join(seperator);
}
}
/**
+1 -8
View File
@@ -209,14 +209,7 @@ class XMLUtil {
if (anim.has.y) animData.y = Std.parseFloat(anim.att.y).getDefault(animData.y);
if (anim.has.loop) animData.loop = anim.att.loop == "true";
if (anim.has.forced) animData.forced = anim.att.forced == "true";
if (anim.has.indices) {
var indicesSplit = anim.att.indices.split(",");
for(indice in indicesSplit) {
var i = Std.parseInt(indice.trim());
if (i != null)
animData.indices.push(i);
}
}
if (anim.has.indices) animData.indices = CoolUtil.parseNumberRange(anim.att.indices);
return animData;
}
@@ -69,7 +69,7 @@ class CharacterAnimScreen extends UISubstateWindow {
addLabelOn(loopedCheckbox, "Looping");
loopedCheckbox.x += 8; loopedCheckbox.y += 6;
indicesTextBox = new UITextBox(nameTextBox.x, nameTextBox.y + 32 + 40, animData.indices.join(", "), 270);
indicesTextBox = new UITextBox(nameTextBox.x, nameTextBox.y + 32 + 40, CoolUtil.formatNumberRange(animData.indices, ", "), 270);
add(indicesTextBox);
addLabelOn(indicesTextBox, "Indices");
@@ -109,14 +109,8 @@ class CharacterAnimScreen extends UISubstateWindow {
animType: NONE,
x: offsetXStepper.value,
y: offsetYStepper.value,
indices: []
indices: CoolUtil.parseNumberRange(indicesTextBox.label.text)
};
var indicesSplit = indicesTextBox.label.text.split(",");
for(indice in indicesSplit) {
var i = Std.parseInt(indice.trim());
if (i != null)
animData.indices.push(i);
}
if (onSave != null) onSave(animData);
}
@@ -194,8 +194,10 @@ class CharacterInfoScreen extends UISubstateWindow {
var offset:FlxPoint = character.getAnimOffset(anim.name);
animXml.set("x", Std.string(offset.x));
animXml.set("y", Std.string(offset.y));
offset.put();
if (anim.indices.length > 0)
animXml.set("indices", anim.indices.join(","));
animXml.set("indices", CoolUtil.formatNumberRange(anim.indices));
xml.addChild(animXml);
}
+1 -1
View File
@@ -396,7 +396,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
offset.putWeak();
if (anim.indices.length > 0)
animXml.set("indices", anim.indices.join(","));
animXml.set("indices", CoolUtil.formatNumberRange(anim.indices));
xml.addChild(animXml);
}
+1 -1
View File
@@ -1261,7 +1261,7 @@ class PlayState extends MusicBeatState
if (Conductor.songPosition >= 0)
startSong();
}
} else {
} else if (FlxG.sound.music != null) {
var instTime = FlxG.sound.music.time;
var isOffsync = vocals.time != instTime || [for(strumLine in strumLines.members) strumLine.vocals.time != instTime].contains(true);
__vocalOffsetViolation = Math.max(0, __vocalOffsetViolation + (isOffsync ? elapsed : -elapsed / 2));
+1 -1
View File
@@ -162,7 +162,7 @@ class MainMenuState extends MusicBeatState
{
case 'story mode': FlxG.switchState(new StoryMenuState());
case 'freeplay': FlxG.switchState(new FreeplayState());
case 'donate': FlxG.switchState(new CreditsMain());
case 'donate', 'credits': FlxG.switchState(new CreditsMain()); // kept donate for not breaking scripts, if you dont want donate to bring you to the credits menu, thats easy softcodable - Nex
case 'options': FlxG.switchState(new OptionsMenu());
}
});
+16 -10
View File
@@ -4,9 +4,11 @@ import funkin.options.OptionsScreen;
import funkin.options.TreeMenu;
import funkin.options.type.*;
import haxe.xml.Access;
import flixel.util.FlxColor;
class CreditsMain extends TreeMenu {
var bg:FlxSprite;
var items:Array<OptionType> = [];
public override function create() {
bg = new FlxSprite(-80).loadGraphic(Paths.image('menus/menuBGBlue'));
@@ -18,7 +20,6 @@ class CreditsMain extends TreeMenu {
bg.antialiasing = true;
add(bg);
var selectables:Array<OptionType> = [];
var xmlPath = Paths.xml('config/credits');
for(source in [funkin.backend.assets.AssetsLibraryList.AssetSource.SOURCE, funkin.backend.assets.AssetsLibraryList.AssetSource.MODS]) {
if (Paths.assetsTree.existsSpecific(xmlPath, "TEXT", source)) {
@@ -31,17 +32,17 @@ class CreditsMain extends TreeMenu {
if (access != null)
for(c in parseCreditsFromXML(access, source))
selectables.push(c);
items.push(c);
}
}
selectables.push(new TextOption("Codename Engine >", "Select this to see all the contributors of the engine!", function() {
items.push(new TextOption("Codename Engine >", "Select this to see all the contributors of the engine!", function() {
optionsTree.add(Type.createInstance(CreditsCodename, []));
}));
selectables.push(new TextOption("Friday Night Funkin'", "Select this to open the itch.io page of the original game to donate!", function() {
items.push(new TextOption("Friday Night Funkin'", "Select this to open the itch.io page of the original game to donate!", function() {
CoolUtil.openURL("https://ninja-muffin24.itch.io/funkin");
}));
main = new OptionsScreen('Credits', 'The people who made this possible!', selectables);
main = new OptionsScreen('Credits', 'The people who made this possible!', items);
super.create();
DiscordUtil.call("onMenuLoaded", ["Credits Menu"]);
@@ -68,11 +69,13 @@ class CreditsMain extends TreeMenu {
html_url: 'https://github.com/$username',
avatar_url: 'https://github.com/$username.png'
};
credsMenus.push(new GithubIconOption(user, desc, null,
var opt:GithubIconOption = new GithubIconOption(user, desc, null,
node.has.customName ? node.att.customName : null, node.has.size ? Std.parseInt(node.att.size) : 96,
node.has.portrait ? node.att.portrait.toLowerCase() == "false" ? false : true : true
));
);
if (node.has.color)
@:privateAccess opt.__text.color = FlxColor.fromString(node.att.color);
credsMenus.push(opt);
} else {
if (!node.has.name) {
Logs.trace("[CreditsMain] A credit node requires a name attribute.", WARNING);
@@ -82,11 +85,14 @@ class CreditsMain extends TreeMenu {
switch(node.name) {
case "credit":
credsMenus.push(new PortraitOption(name, desc, function() if(node.has.url) CoolUtil.openURL(node.att.url),
var opt:PortraitOption = new PortraitOption(name, desc, function() if(node.has.url) CoolUtil.openURL(node.att.url),
node.has.icon && Paths.assetsTree.existsSpecific(Paths.image('credits/${node.att.icon}'), "IMAGE", source) ?
FlxG.bitmap.add(Paths.image('credits/${node.att.icon}')) : null, node.has.size ? Std.parseInt(node.att.size) : 96,
node.has.portrait ? node.att.portrait.toLowerCase() == "false" ? false : true : true
));
);
if (node.has.color)
@:privateAccess opt.__text.color = FlxColor.fromString(node.att.color);
credsMenus.push(opt);
case "menu":
credsMenus.push(new TextOption(name + " >", desc, function() {