11package ;
22
3+ import haxe .Json ;
4+ import openfl .utils .Assets ;
5+
36using StringTools ;
47
8+ // metadatas for icons
9+ // allows for animated icons and such
10+ typedef IconMeta = {
11+ ? noAntialiasing : Bool ,
12+ ? fps : Int ,
13+ // ?frameOrder:Array<String> // ["normal", "losing", "winning"]
14+ // ?isAnimated:Bool,
15+ ? hasWinIcon : Bool ,
16+ }
517class HealthIcon extends FlxSprite
618{
719 public var sprTracker : FlxSprite ;
820 public var canBounce : Bool = false ;
921 private var isPlayer : Bool = false ;
1022 private var char : String = ' ' ;
23+ public var iconMeta : IconMeta ;
1124
1225 var initialWidth : Float = 0 ;
1326 var initialHeight : Float = 0 ;
@@ -37,6 +50,10 @@ class HealthIcon extends FlxSprite
3750 public var iconOffsets : Array <Float > = [0 , 0 ];
3851 public function changeIcon (char : String ) {
3952 if (this .char != char ) {
53+ if (char .length < 1 )
54+ char = ' face' ;
55+
56+ iconMeta = getFile (char );
4057 var name : String = ' icons/' + char ;
4158 if (! Paths .fileExists (' images/' + name + ' .png' , IMAGE )) name = ' icons/icon-' + char ; // Older versions of psych engine's support
4259 if (! Paths .fileExists (' images/' + name + ' .png' , IMAGE )) name = ' icons/icon-face' ; // Prevents crash from missing icon
@@ -48,7 +65,6 @@ class HealthIcon extends FlxSprite
4865 // throw "Don't delete the placeholder icon";
4966 trace (" Warning: could not find the placeholder icon, expect crashes!" );
5067 }
51-
5268 final iSize : Float = Math .round (file .width / file .height );
5369 /*
5470 loadGraphic(file, true, Math.floor(file.width / iSize), Math.floor(file.height));
@@ -75,6 +91,23 @@ class HealthIcon extends FlxSprite
7591 initialHeight = height ;
7692 updateHitbox ();
7793 animation .add (char , [0 , 1 , 2 ], 0 , false , isPlayer );
94+ } else if (Paths .fileExists (' images/ $name .xml' , TEXT )) {
95+ frames = Paths .getSparrowAtlas (name );
96+ final iconPrefixes = checkAvailablePrefixes (Paths .getPath (' images/ $name .xml' , TEXT ));
97+ final hasWinning = iconPrefixes .get (' winning' );
98+ final hasLosing = iconPrefixes .get (' losing' );
99+ final fps : Float = iconMeta .fps ?? = 24 ;
100+ final loop = fps > 0 ;
101+
102+ // Always add "normal"
103+ animation .addByPrefix (' normal' , ' normal' , fps , loop , isPlayer );
104+
105+ // Add "losing", fallback to "normal"
106+ animation .addByPrefix (' losing' , hasLosing ? ' losing' : ' normal' , fps , loop , isPlayer );
107+
108+ // Add "winning", fallback to "normal"
109+ animation .addByPrefix (' winning' , hasWinning ? ' winning' : ' normal' , fps , loop , isPlayer );
110+ playAnim (' normal' );
78111 } else { // This is just an attempt for other icon support, will detect is less than 300 or more than 300. If 300 or less, only 2 icons, if more, 3 icons.
79112 var num : Int = Std .int (Math .round (file .width / file .height ));
80113 if (file .width % file .height != 0 ) {
@@ -93,20 +126,45 @@ class HealthIcon extends FlxSprite
93126 initialWidth = width ;
94127 initialHeight = height ;
95128 updateHitbox ();
96- animation .add (char , num == 2 ? [0 , 1 ] : [0 , 1 , 2 ], 0 , false , isPlayer );
129+
130+ function getWinIcon (): Array <Int >
131+ {
132+ return (iconMeta ?. hasWinIcon || num == 3 ) ? [0 , 1 , 2 ] : [0 , 1 ];
133+ }
134+
135+ final winShit : Array <Int > = (num == 2 ) ? [0 , 1 ] : getWinIcon ();
136+ animation .add (char , winShit , 0 , false , isPlayer );
97137 }
98138
99139 // animation.add(char, [for(i in 0...frames.frames.length) i], 0, false, isPlayer);
100140 animation .play (char );
101141 this .char = char ;
102142
103- antialiasing = ClientPrefs .globalAntialiasing ;
143+ antialiasing = ( ClientPrefs .globalAntialiasing || iconMeta ?. noAntialiasing ) ;
104144 if (char .endsWith (' -pixel' )) {
105145 antialiasing = false ;
106146 }
107147 }
108148 }
109149
150+ function checkAvailablePrefixes (xmlPath : String ): Map <String , Bool > {
151+ final result = new Map <String , Bool >();
152+ result .set (" normal" , false );
153+ result .set (" losing" , false );
154+ result .set (" winning" , false );
155+
156+ final xml : Xml = Xml .parse (Assets .getText (xmlPath ));
157+ final root : Xml = xml .firstElement ();
158+ for (node in root .elements ()) {
159+ final name = node .get (" name" );
160+ for (prefix in result .keys ()) {
161+ if (name .startsWith (prefix )) result .set (prefix , true );
162+ }
163+ }
164+
165+ return result ;
166+ }
167+
110168 public function bounce () {
111169 if (canBounce ) {
112170 var mult : Float = 1.2 ;
@@ -115,6 +173,32 @@ class HealthIcon extends FlxSprite
115173 }
116174 }
117175
176+ public function playAnim (anim : String ) {
177+ if (animation .exists (anim ))
178+ animation .play (anim );
179+ }
180+
181+ public static function getFile (name : String ): IconMeta {
182+ var characterPath : String = ' images/icons/ $name .json' ;
183+ var path : String = Paths .getPath (characterPath );
184+ if (! Paths .exists (path , TEXT ))
185+ {
186+ path = Paths .getPreloadPath (' images/icons/bf.json' ); // If a character couldn't be found, change them to BF just to prevent a crash
187+ }
188+
189+ var rawJson = Paths .getContent (path );
190+ if (rawJson == null ) {
191+ return null ;
192+ }
193+
194+ var json : IconMeta = cast Json .parse (rawJson );
195+ if (json .noAntialiasing == null ) json .noAntialiasing = false ;
196+ if (json .fps == null ) json .fps = 24 ;
197+ if (json .hasWinIcon == null ) json .hasWinIcon = true ;
198+ // if (json.frameOrder == null) json.frameOrder = ['normal', 'losing', 'winning'];
199+ return json ;
200+ }
201+
118202 override function updateHitbox ()
119203 {
120204 if (ClientPrefs .iconBounceType != ' Golden Apple' && ClientPrefs .iconBounceType != ' Dave and Bambi' || ! Std .isOfType (FlxG .state , PlayState ))
0 commit comments