├── .gitattributes
├── LICENSE
├── README.md
├── assets
├── eventArrowModchart.png
├── eventArrowModchart.xml
└── pathTest.txt
├── documentation
└── ModchartVariables.txt
├── examples
├── customPath.txt
├── leather
│ ├── modchart.lua
│ └── modifiers.hx
├── modchart editor testing
│ └── fusion-reactor
│ │ ├── customMods
│ │ ├── IncomingAngleCurve.hx
│ │ ├── IncomingAngleSmooth.hx
│ │ ├── InvertIncomingAngle.hx
│ │ └── MoveYWaveShit.hx
│ │ ├── fusion-reactor-canon.json
│ │ └── modchart.json
├── psych
│ └── script.lua
└── readme.txt
├── haxelib.json
├── include.xml
├── readme
├── custommods.gif
├── modifiers.gif
└── sustains.gif
└── source
├── flixel
├── addons
│ └── effects
│ │ └── FlxSkewedSprite.hx
└── tweens
│ └── misc
│ ├── BezierPathNumTween.hx
│ └── BezierPathTween.hx
├── import.hx
├── managers
└── TweenManager.hx
└── modcharting
├── ModTable.hx
├── ModchartEditorState.hx
├── ModchartEvent.hx
├── ModchartEventManager.hx
├── ModchartFile.hx
├── ModchartFuncs.hx
├── ModchartMusicBeatState.hx
├── ModchartUtil.hx
├── Modifier.hx
├── NoteMovement.hx
├── NotePositionData.hx
├── Playfield.hx
├── PlayfieldRenderer.hx
├── SimpleQuaternion.hx
└── SustainStrip.hx
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FNF Modcharting Tools
2 | Just a thing I made to make modcharting easier, should be easy to add to most engines.
3 | Still very WIP and not everything is supported yet!
4 |
5 | ## Features
6 | ### Modifier system for easing in and out effects
7 | 
8 | ### Custom Sustain Renderer (using FlxStrip for stretchy sustains)
9 | ### Multiple playfields that can have their own positions and modifiers
10 | 
11 | ### Custom Modifier Support via Hscript
12 | 
13 | ### Support for multiple engines
14 | - Base Game (not tested)
15 | - [Psych Engine](https://github.com/ShadowMario/FNF-PsychEngine) (working 0.6.3 and 0.7.x, includes lua functions)
16 | - [Leather Engine](https://github.com/Leather128/LeatherEngine) (working 0.5.0)
17 | - [Kade Engine](https://github.com/KadeDev/Kade-Engine) (not tested)
18 | - [Yoshi Engine](https://github.com/YoshiCrafter29/YoshiCrafterEngine) (not tested)
19 | - [Forever Engine Legacy](https://github.com/Yoshubs/Forever-Engine-Legacy) (not tested)
20 | - [FPS Plus](https://github.com/ThatRozebudDude/FPS-Plus-Public) (not tested)
21 |
22 |
23 | ## Credits
24 | - [Original FNF Team](https://github.com/ninjamuffin99/Funkin) - They made the game
25 | - [NotITG](https://www.noti.tg/) - Inspiration (made me love modcharts lol)
26 | - [OpenITG](https://github.com/openitg/openitg) - Math used for some modifiers
27 | - [TheZoroForce240](https://github.com/TheZoroForce240/FNF-Modcharting-Tools) - Creator of modcharting tools base
28 | - [Vortex2Oblivion](https://github.com/Vortex2Oblivion) - Helper from modcharting tools
29 | - [Manu614](https://github.com/Manu614) - Helper from modcharting tools
30 | - [UncertainProd](https://github.com/UncertainProd) - Helper from modcharting tools
31 | - [Joalor64GH](https://github.com/Joalor64GH) - Helper from modcharting tools
32 | - [Edwhak_KB](https://github.com/EdwhakKB) - Added some modifiers and fixed stuff + skewNotes
33 | - [Glowsoony](https://github.com/glowsoony) - Help with some 0.7.X stuff! + skewNotes too
34 | - [Slushi_Github](https://github.com/Slushi-Github) - Help with reorganisation with haxelib edition
35 | - [2JENO](https://github.com/2JENO) - Help with the Import.hx, GPU thing (fixes some things so thanks!)
36 |
37 | ## Installation
38 | 1. You need the most recent version of HaxeFlixel for it to work. (5.5.0 as of writing)
39 | 2. If your running any (engine or psych) that uses SScript (For Custom Modifiers) then I really recommened using versions 6.1.80 and up. NO LOWER VERSIONS! (If you use older versions, sorry but SScript in older version apperantly has many memory leaks when it comes to any scripts (even without modchartingTools). -glowsoony
40 | ### With Source:
41 | 1. Install the haxelib by typing `haxelib git fnf-modcharting-tools https://github.com/EdwhakKB/FNF-Modcharting-Tools` in the console
42 | 2. Now you only need to make a few small additions to get everything working,
43 | - In MusicBeatState.hx:
44 | ```haxe
45 | class MusicBeatState extends modcharting.ModchartMusicBeatState
46 | {
47 |
48 | ```
49 | - In PlayState.hx:
50 | ```haxe
51 | import modcharting.ModchartFuncs;
52 | import modcharting.NoteMovement;
53 | import modcharting.PlayfieldRenderer;
54 |
55 | ```
56 | ```haxe
57 | override public function create()
58 | {
59 | //Add this before function create() (For Psych 0.7.1+)
60 | var backupGpu:Bool;
61 | //Add this before generateSong(); (For Psych 0.7.1+)
62 | backupGpu = ClientPrefs.data.cacheOnGPU;
63 | ClientPrefs.data.cacheOnGPU = false;
64 | //Add this before camfollow stuff and after strumLineNotes and notes have been made
65 | playfieldRenderer = new PlayfieldRenderer(strumLineNotes, notes, this);
66 | playfieldRenderer.cameras = [camHUD];
67 | add(playfieldRenderer);
68 | add(grpNoteSplashes); /*place splashes in front (add this if the engine has splashes).
69 | If you have added this: remove(or something) the add(grpNoteSplashes); which is by default below the add(strumLineNotes);*/
70 | //if you use PSYCH 0.6.3 use this code
71 | ModchartFuncs.loadLuaFunctions(); //add this if you want lua functions in scripts
72 | //being used in psych engine as an example
73 | callOnLuas('onCreatePost', []);
74 |
75 | //Find this line and then add it
76 | public function startCountdown():Void
77 | {
78 | generateStaticArrows(0);
79 | generateStaticArrows(1);
80 |
81 | //add after generating strums
82 | NoteMovement.getDefaultStrumPos(this);
83 | //Find this line and then add it (For Psych 0.7.1+)
84 | override function destroy() {
85 | ClientPrefs.data.cacheOnGPU = backupGpu;
86 | ```
87 |
88 | - In StrumNote.hx:
89 | ```haxe
90 | //Import FlxSkewedSprite at the top
91 | import flixel.addons.effects.FlxSkewedSprite;
92 | //change "FlxSprite" to "FlxSkewedSprite"
93 | class StrumNote extends FlxSkewedSprite
94 | ```
95 |
96 | - In Note.hx:
97 | ```haxe
98 | //Import FlxSkewedSprite at the top
99 | import flixel.addons.effects.FlxSkewedSprite;
100 | //change "FlxSprite" to "FlxSkewedSprite"
101 | class Note extends FlxSkewedSprite
102 | {
103 | //add these 2 variables for the renderer
104 | public var mesh:modcharting.SustainStrip = null;
105 | public var z:Float = 0;
106 | ```
107 |
108 | - In ModchartUtilities.hx (Leather Exclusive):
109 |
110 | ```haxe
111 | // at the start of the HX
112 | import modcharting.ModchartFuncs; //to fix any crash lmao
113 | // (at the bottom of create())
114 | #if desktop DiscordClient.addLuaCallbacks(this); #end
115 | ModchartFuncs.loadLuaFunctions(this); //add this if you want lua functions in scripts
116 | //being used in leather engine as an example
117 | callOnLuas('onCreate', []);
118 | ```
119 |
120 | - In FunkinLua.hx (Found in psychlua folder) (0.7.X exclusive!):
121 | ```haxe
122 | //at the start of the HX
123 | import modcharting.ModchartFuncs; //to fix any crash lmao
124 | class FunkinLua
125 | {
126 | //add this variable bellow "public var closed:Bool = false;"
127 | public static var instance:FunkinLua = null;
128 | #if desktop DiscordClient.addLuaCallbacks(this); #end
129 | ModchartFuncs.loadLuaFunctions(this); //add this if you want lua functions in scripts
130 | being used in psych engine as an example
131 | ```
132 | - In HScript (Found in psychlua folder) (0.7.X exclusive!)
133 | ``` haxe
134 | //under the function (PRESET!)
135 | //copy and paste this code if you use under SScript 6.1.80
136 | override function preset()
137 | {
138 | set('Math', Math);
139 | set('ModchartEditorState', modcharting.ModchartEditorState);
140 | set('ModchartEvent', modcharting.ModchartEvent);
141 | set('ModchartEventManager', modcharting.ModchartEventManager);
142 | set('ModchartFile', modcharting.ModchartFile);
143 | set('ModchartFuncs', modcharting.ModchartFuncs);
144 | set('ModchartMusicBeatState', modcharting.ModchartMusicBeatState);
145 | set('ModchartUtil', modcharting.ModchartUtil);
146 | for (i in ['mod', 'Modifier'])
147 | set(i, modcharting.Modifier); //the game crashes without this???????? what??????????? -- fue glow
148 | set('ModifierSubValue', modcharting.Modifier.ModifierSubValue);
149 | set('ModTable', modcharting.ModTable);
150 | set('NoteMovement', modcharting.NoteMovement);
151 | set('NotePositionData', modcharting.NotePositionData);
152 | set('Playfield', modcharting.Playfield);
153 | set('PlayfieldRenderer', modcharting.PlayfieldRenderer);
154 | set('SimpleQuaternion', modcharting.SimpleQuaternion);
155 | set('SustainStrip', modcharting.SustainStrip);
156 |
157 | modcharting.ModchartFuncs.loadHScriptFunctions(this);
158 | //--(else if you use SScript above or equal to version 6.1.80)--
159 | override function preset()
160 | {
161 | set('Math', Math);
162 | setClass(modcharting.ModchartEditorState);
163 | setClass(modcharting.ModchartEvent);
164 | setClass(modcharting.ModchartEventManager);
165 | setClass(modcharting.ModchartFile);
166 | setClass(modcharting.ModchartFuncs);
167 | setClass(modcharting.ModchartMusicBeatState);
168 | setClass(modcharting.ModchartUtil);
169 | setClass(modcharting.Modifier); //the game crashes without this???????? what??????????? -- fue glow
170 | setClass(modcharting.Modifier.ModifierSubValue);
171 | setClass(modcharting.ModTable);
172 | setClass(modcharting.NoteMovement);
173 | setClass(modcharting.NotePositionData);
174 | setClass(modcharting.Playfield);
175 | setClass(modcharting.PlayfieldRenderer);
176 | setClass(modcharting.SimpleQuaternion);
177 | setClass(modcharting.SustainStrip);
178 | modcharting.ModchartFuncs.loadHScriptFunctions(this);
179 | //Function initMod -- Init's the mods functions for Hscript (found in psychlua)
180 | //Place this function anywhere in the HScript class!
181 | public function initMod(mod:modcharting.Modifier)
182 | {
183 | call("initMod", [mod]);
184 | }
185 | ```
186 | - In Import.hx, you should copy what mine adds and paste it there
187 |
188 | - In Project.xml:
189 | ```xml
190 |
191 |
192 |
193 |
194 |
195 | ```
196 | You need to define which engine you're using to fix compiling issues, or it would default to base game settings (downscroll won't work etc).
197 | Available ones: PSYCH, KADE(notTested), LEATHER, FOREVER_LEGACY(notTested), YOSHI(notTested), FPSPLUS(notTested)
198 |
199 | Note: If you use psych engine you should add this (have in mind "ver" is the version you want to use, do not add the text, use the brain)
200 | (just in case minimal ver is 0.6.0 to 0.7.3)
201 | and no if psych 0.7.4 or more releases i won't port this due some changes Psych has (they break MT to it max so srry :D)
202 |
203 | ```xml
204 |
205 |
206 |
207 | ```
208 |
209 | to get 0.7.X and up add a higher version than 0.7 (example 0.7.3),
210 | leave it as another value to use 0.6.3 edition
211 |
212 |
213 | 3. Now if your game compiles successfully then you should be all good to go.
214 |
--------------------------------------------------------------------------------
/assets/eventArrowModchart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EdwhakKB/FNF-Modcharting-Tools/47a411c67e7deaa39c4e29d8640c8b2f4e36ea7d/assets/eventArrowModchart.png
--------------------------------------------------------------------------------
/assets/eventArrowModchart.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/assets/pathTest.txt:
--------------------------------------------------------------------------------
1 | -5.32266902923584;1.5246357917785645;-8.777054786682129;1.0
2 | -5.234609603881836;1.7484805583953857;-8.783271789550781;1.0
3 | -4.900301456451416;2.3798604011535645;-8.810586929321289;1.0
4 | -4.539057731628418;2.6687521934509277;-8.846787452697754;1.0
5 | -3.8826723098754883;2.9988062381744385;-8.915874481201172;1.0
6 | -3.499480724334717;3.0214765071868896;-8.959095001220703;1.0
7 | -3.3510608673095703;2.920449733734131;-8.977700233459473;1.0
8 | -3.23814058303833;2.734546661376953;-8.9937105178833;1.0
9 | -3.2129225730895996;2.4665908813476562;-9.00113296508789;1.0
10 | -3.3027024269104004;2.1242594718933105;-8.996732711791992;1.0
11 | -3.628297805786133;1.5280909538269043;-8.969809532165527;1.0
12 | -3.9624013900756836;1.1121773719787598;-8.938857078552246;1.0
13 | -4.432987213134766;0.7346479296684265;-8.89172077178955;1.0
14 | -4.989719390869141;0.47027212381362915;-8.832858085632324;1.0
15 | -5.33845329284668;0.40233945846557617;-8.794328689575195;1.0
16 | -5.050148010253906;0.45850127935409546;-8.82618236541748;1.0
17 | -5.029303073883057;0.5452755093574524;-8.827080726623535;1.0
18 | -4.391894817352295;2.143267869949341;-8.872462272644043;1.0
19 | -4.3830060958862305;2.175076484680176;-8.872934341430664;1.0
20 | -5.2553277015686035;0.3583762049674988;-8.804534912109375;1.0
21 | -5.1723856925964355;-0.4300546944141388;-8.82736873626709;1.0
22 | -5.1723856925964355;-0.4300546944141388;-8.82736873626709;1.0
23 | -5.05217981338501;0.43756574392318726;-8.826306343078613;1.0
24 | -4.981097221374512;0.47317057847976685;-8.83379077911377;1.0
25 | -4.445980548858643;0.7297149300575256;-8.890326499938965;1.0
26 | -4.422902584075928;0.6993982195854187;-8.893467903137207;1.0
27 | -4.289186954498291;0.33815646171569824;-8.914822578430176;1.0
28 | -3.974761962890625;-0.13148707151412964;-8.95858383178711;1.0
29 | -3.7403483390808105;-0.294700026512146;-8.988033294677734;1.0
30 | -3.6869254112243652;-0.2799406349658966;-8.993861198425293;1.0
31 | -3.5333566665649414;0.07199054956436157;-9.005355834960938;1.0
32 | -3.3668928146362305;0.2654244303703308;-9.021012306213379;1.0
33 | -3.148952007293701;0.4384259581565857;-9.042874336242676;1.0
34 | -2.9370603561401367;0.688578188419342;-9.062736511230469;1.0
35 | -2.8379602432250977;0.8949999213218689;-9.070507049560547;1.0
36 | -2.75022554397583;1.138371467590332;-9.07635498046875;1.0
37 | -2.7764339447021484;1.2986266613006592;-9.070649147033691;1.0
38 | -2.8319082260131836;1.3400392532348633;-9.06363296508789;1.0
39 | -2.9218978881835938;1.3355627059936523;-9.053467750549316;1.0
40 | -3.004868507385254;1.2715349197387695;-9.045114517211914;1.0
41 | -3.1828699111938477;1.093257188796997;-9.027887344360352;1.0
42 | -3.3691816329956055;0.7088391184806824;-9.013216972351074;1.0
43 | -3.422018527984619;0.3504212498664856;-9.01329517364502;1.0
44 | -3.3937621116638184;0.13399535417556763;-9.020188331604004;1.0
45 | -3.328347682952881;0.08581626415252686;-9.028450965881348;1.0
46 | -3.1835060119628906;0.07486605644226074;-9.045119285583496;1.0
47 | -2.993687152862549;0.16841357946395874;-9.065130233764648;1.0
48 | -2.8458547592163086;0.32340675592422485;-9.079319953918457;1.0
49 | -2.653045654296875;0.5828946232795715;-9.09685230255127;1.0
50 | -2.5239481925964355;0.7908092141151428;-9.108009338378906;1.0
51 | -2.2325916290283203;1.3958618640899658;-9.130884170532227;1.0
52 | -2.1974499225616455;1.4157617092132568;-9.13454532623291;1.0
53 | -2.442473888397217;0.7718679308891296;-9.11760425567627;1.0
54 | -2.5173850059509277;0.256844162940979;-9.117829322814941;1.0
55 | -2.412655830383301;0.2293778657913208;-9.13021469116211;1.0
56 | -2.3232898712158203;0.25984084606170654;-9.139866828918457;1.0
57 | -2.179804801940918;0.39222943782806396;-9.153944969177246;1.0
58 | -2.002357244491577;0.709648072719574;-9.168745040893555;1.0
59 | -1.702239751815796;1.4730639457702637;-9.189926147460938;1.0
60 | -1.635328769683838;1.507857322692871;-9.196949005126953;1.0
61 | -1.62910795211792;1.452498435974121;-9.198596954345703;1.0
62 | -1.8891115188598633;0.7055982947349548;-9.181700706481934;1.0
63 | -1.865096092224121;0.3752055764198303;-9.190047264099121;1.0
64 | -1.7820234298706055;0.3478724956512451;-9.199965476989746;1.0
65 | -1.7135133743286133;0.37427324056625366;-9.207313537597656;1.0
66 | -1.570199966430664;0.48486971855163574;-9.221742630004883;1.0
67 | -1.4240710735321045;0.7396168112754822;-9.23404312133789;1.0
68 | -1.1689012050628662;1.1940202713012695;-9.255358695983887;1.0
69 | -1.050473690032959;1.5260505676269531;-9.26319408416748;1.0
70 | -1.0765066146850586;1.7080979347229004;-9.2571382522583;1.0
71 | -1.1446678638458252;1.7252795696258545;-9.249089241027832;1.0
72 | -1.2324354648590088;1.6864259243011475;-9.239762306213379;1.0
73 | -1.2838106155395508;1.615495204925537;-9.235121726989746;1.0
74 | -1.3679986000061035;1.398923397064209;-9.229220390319824;1.0
75 | -1.3923673629760742;1.163543939590454;-9.230446815490723;1.0
76 | -1.3569157123565674;0.9093559384346008;-9.238801002502441;1.0
77 | -1.279334306716919;0.8200300335884094;-9.249147415161133;1.0
78 | -1.154201865196228;0.8444053530693054;-9.262971878051758;1.0
79 | -1.0420336723327637;0.9141233563423157;-9.274552345275879;1.0
80 | -0.8950022459030151;1.0733113288879395;-9.288578987121582;1.0
81 | -0.7072662115097046;1.4275479316711426;-9.303923606872559;1.0
82 | -0.5383337736129761;1.7215492725372314;-9.31815242767334;1.0
83 | -0.39519548416137695;1.8103539943695068;-9.332931518554688;1.0
84 | -0.33005672693252563;1.8317453861236572;-9.339981079101562;1.0
85 | -0.25195416808128357;1.8077962398529053;-9.349276542663574;1.0
86 | -0.21208593249320984;1.6893668174743652;-9.35582447052002;1.0
87 | -0.2257145494222641;1.443023920059204;-9.35845947265625;1.0
88 | -0.3607226014137268;1.0163805484771729;-9.350346565246582;1.0
89 | -0.4754299521446228;0.7329409718513489;-9.342108726501465;1.0
90 | -0.6449167132377625;0.578081488609314;-9.32545280456543;1.0
91 | -0.7376539707183838;0.5426102876663208;-9.315503120422363;1.0
92 | -0.8489514589309692;0.5818514823913574;-9.302170753479004;1.0
93 | -0.878355860710144;0.758889377117157;-9.295815467834473;1.0
94 | -0.8644500970840454;0.9356613755226135;-9.294394493103027;1.0
95 | -0.8468254804611206;1.161024570465088;-9.292571067810059;1.0
96 | -0.8468254804611206;1.161024570465088;-9.292571067810059;1.0
97 | -0.7261083126068115;1.0496416091918945;-9.308199882507324;1.0
98 | -0.7112677097320557;0.9263364672660828;-9.31198501586914;1.0
99 | -0.633686363697052;0.8370113968849182;-9.322330474853516;1.0
100 | -0.5215896964073181;0.7935743927955627;-9.33582592010498;1.0
101 | -0.31783077120780945;0.8593752980232239;-9.357893943786621;1.0
102 | -0.10308815538883209;1.0491602420806885;-9.379106521606445;1.0
103 | 0.11527067422866821;1.3789005279541016;-9.398353576660156;1.0
104 | 0.3083258867263794;1.7733361721038818;-9.413619995117188;1.0
105 | 0.3854227662086487;1.936307430267334;-9.419624328613281;1.0
106 | 0.3845199942588806;2.0318660736083984;-9.41789722442627;1.0
107 | 0.40919923782348633;1.9931573867797852;-9.42136287689209;1.0
108 | 0.45660877227783203;1.8805487155914307;-9.428672790527344;1.0
109 | 0.5648127794265747;1.7667279243469238;-9.44291877746582;1.0
110 | 0.56011962890625;1.700540542602539;-9.443509101867676;1.0
111 | 0.3671293258666992;0.8970697522163391;-9.435200691223145;1.0
112 | 0.4065456986427307;0.8264201283454895;-9.440886497497559;1.0
113 | 0.5124216079711914;0.8383412957191467;-9.45273208618164;1.0
114 | 0.5950434803962708;0.858787477016449;-9.461787223815918;1.0
115 | 0.9431252479553223;1.3704533576965332;-9.492703437805176;1.0
116 | 1.0598821640014648;1.5977203845977783;-9.502127647399902;1.0
117 | 1.4972403049468994;2.9213738441467285;-9.529407501220703;1.0
118 | 1.5103371143341064;2.9343698024749756;-9.530677795410156;1.0
119 | 0.9662704467773438;0.9311016201972961;-9.502802848815918;1.0
120 | 0.9534022808074951;0.9259839653968811;-9.501425743103027;1.0
121 | 0.9314626455307007;0.93215411901474;-9.498824119567871;1.0
122 | 0.9314626455307007;0.93215411901474;-9.498824119567871;1.0
123 | 1.1842787265777588;1.6759123802185059;-9.5149564743042;1.0
124 | 1.4127733707427979;2.00240421295166;-9.535408973693848;1.0
125 | 1.609025001525879;2.171180486679077;-9.554875373840332;1.0
126 | 1.7691943645477295;2.2023813724517822;-9.572571754455566;1.0
127 | 1.8297145366668701;2.020961046218872;-9.582541465759277;1.0
128 | 1.7647697925567627;1.8986501693725586;-9.577229499816895;1.0
129 | 1.5185906887054443;1.6104891300201416;-9.554110527038574;1.0
130 | 1.3787741661071777;1.4997029304504395;-9.540082931518555;1.0
131 | 1.3916633129119873;1.4865474700927734;-9.541773796081543;1.0
132 | 1.4837167263031006;1.2486069202423096;-9.556291580200195;1.0
133 | 1.6066365242004395;1.1211166381835938;-9.5724458694458;1.0
134 | 1.7032382488250732;1.0772719383239746;-9.584182739257812;1.0
135 | 1.8228232860565186;1.1580073833465576;-9.596420288085938;1.0
136 | 2.0222456455230713;1.47361421585083;-9.613750457763672;1.0
137 | 2.0773041248321533;1.4843401908874512;-9.619833946228027;1.0
138 | 2.189255475997925;1.3599352836608887;-9.634688377380371;1.0
139 | 2.350801944732666;1.438401460647583;-9.651739120483398;1.0
140 | 2.6131649017333984;1.7506022453308105;-9.676289558410645;1.0
141 | 2.7996997833251953;2.079364538192749;-9.691929817199707;1.0
142 | 2.8237266540527344;2.334696054458618;-9.690325736999512;1.0
143 | 2.788565158843994;2.4375061988830566;-9.684577941894531;1.0
144 | 2.7406396865844727;2.443836212158203;-9.67901611328125;1.0
145 | 2.6755714416503906;2.4311606884002686;-9.67182731628418;1.0
146 | 2.536923885345459;2.341489553451538;-9.657572746276855;1.0
147 | 2.29437255859375;2.007037401199341;-9.63565444946289;1.0
148 | 2.171407461166382;1.7533199787139893;-9.625971794128418;1.0
149 | 2.1400363445281982;1.4547853469848633;-9.627476692199707;1.0
150 | 2.1939661502838135;1.1989738941192627;-9.637959480285645;1.0
151 | 2.353717803955078;1.1778738498687744;-9.65649700164795;1.0
152 | 2.6263413429260254;1.2727558612823486;-9.685907363891602;1.0
153 | 2.9553589820861816;1.6710479259490967;-9.716582298278809;1.0
154 | 3.000405788421631;1.679823875427246;-9.721559524536133;1.0
155 | 2.9933981895446777;1.5531325340270996;-9.72291374206543;1.0
156 | 3.02059268951416;1.3286681175231934;-9.729823112487793;1.0
157 | 3.1324172019958496;1.3138971328735352;-9.742798805236816;1.0
158 | 3.3282508850097656;1.4303734302520752;-9.763105392456055;1.0
159 | 3.501059055328369;1.6676909923553467;-9.778738975524902;1.0
160 | 3.5897412300109863;1.8833961486816406;-9.785164833068848;1.0
161 | 3.694146156311035;2.3162624835968018;-9.789690017700195;1.0
162 | 3.6840972900390625;2.5597355365753174;-9.784409523010254;1.0
163 | 3.577275276184082;2.575479507446289;-9.77198600769043;1.0
164 | 3.3922033309936523;2.4297685623168945;-9.753402709960938;1.0
165 | 3.193948268890381;2.1352765560150146;-9.735844612121582;1.0
166 | 3.0453295707702637;1.7982337474822998;-9.724658966064453;1.0
167 | 3.0030760765075684;1.6385674476623535;-9.722563743591309;1.0
168 | 3.007911205291748;1.367973804473877;-9.72771167755127;1.0
169 | 3.100468158721924;1.3181183338165283;-9.739092826843262;1.0
170 | 3.1865158081054688;1.3296592235565186;-9.748687744140625;1.0
171 | 3.3563642501831055;1.4462940692901611;-9.766033172607422;1.0
172 | 3.5131988525390625;1.685720682144165;-9.779813766479492;1.0
173 | 4.116020202636719;3.453263759613037;-9.818379402160645;1.0
174 | 3.652557849884033;1.9896275997161865;-9.790508270263672;1.0
175 | 3.6366610527038574;1.5008947849273682;-9.797003746032715;1.0
176 | 3.6822500228881836;1.4523355960845947;-9.803016662597656;1.0
177 | 3.757538318634033;1.493109941482544;-9.810890197753906;1.0
178 | 3.854224681854248;1.5850520133972168;-9.820331573486328;1.0
179 | 4.037461757659912;1.8766188621520996;-9.83622932434082;1.0
180 | 4.1816182136535645;2.1553494930267334;-9.847896575927734;1.0
181 | 4.156808376312256;1.4315543174743652;-9.857372283935547;1.0
182 | 3.0348057746887207;0.9790293574333191;-9.737380981445312;1.0
183 | -1.1645309925079346;0.2741355299949646;-9.27148723602295;1.0
184 | -3.966914653778076;-0.554682731628418;-8.966667175292969;1.0
185 | -5.333769798278809;-2.132967233657837;-8.837940216064453;1.0
186 | -3.6712446212768555;-2.838393211364746;-9.039117813110352;1.0
187 | -2.976569652557373;-2.576744318008423;-9.113723754882812;1.0
188 | -2.170823097229004;-1.815215826034546;-9.192476272583008;1.0
189 | -1.8277311325073242;-1.0265085697174072;-9.218117713928223;1.0
190 | -1.781813144683838;-0.4671350121498108;-9.213837623596191;1.0
191 | -1.951695442199707;-0.3287825584411621;-9.192154884338379;1.0
192 | -2.1326065063476562;-0.2737894058227539;-9.170633316040039;1.0
193 | -2.383432388305664;-0.32264968752861023;-9.14292049407959;1.0
194 | -3.0035791397094727;-0.551734209060669;-9.076240539550781;1.0
195 | -3.3513498306274414;-0.8450651168823242;-9.04164981842041;1.0
196 | -3.7364578247070312;-1.2719969749450684;-9.005081176757812;1.0
197 | -3.8871021270751953;-1.7525136470794678;-8.996102333068848;1.0
198 | -3.1969618797302246;-0.7608497142791748;-9.057788848876953;1.0
199 | -2.5893545150756836;-0.37178659439086914;-9.120321273803711;1.0
200 | -1.9719481468200684;-0.269563764333725;-9.188843727111816;1.0
201 | -1.7769865989685059;-0.7278742790222168;-9.218816757202148;1.0
202 | -1.9574003219604492;-1.4758691787719727;-9.210996627807617;1.0
203 | -2.7033262252807617;-2.315976619720459;-9.140387535095215;1.0
204 | -3.2054858207702637;-2.6935245990753174;-9.089658737182617;1.0
205 | -3.5897250175476074;-2.7954421043395996;-9.047664642333984;1.0
206 | -2.880189895629883;-1.1051981449127197;-9.099687576293945;1.0
207 | -3.6013293266296387;-2.7345387935638428;-9.045309066772461;1.0
208 | -3.725451946258545;-3.3542640209198;-9.041714668273926;1.0
209 | -3.719327449798584;-3.6688919067382812;-9.047758102416992;1.0
210 | -3.622664451599121;-2.810882806777954;-9.04417896270752;1.0
211 | -3.3262133598327637;-2.6719236373901367;-9.075553894042969;1.0
212 | -3.0164999961853027;-2.602569103240967;-9.109619140625;1.0
213 | -2.9075231552124023;-2.7979037761688232;-9.125337600708008;1.0
214 | -2.773679733276367;-3.123744010925293;-9.146106719970703;1.0
215 | -2.537705421447754;-3.420666456222534;-9.17800521850586;1.0
216 | -2.2643957138061523;-3.583988904953003;-9.211881637573242;1.0
217 | -1.9039382934570312;-3.2160000801086426;-9.246648788452148;1.0
218 | -1.9124400615692139;-2.9830470085144043;-9.24172306060791;1.0
219 | -1.8530457019805908;-2.6827266216278076;-9.243378639221191;1.0
220 | -1.7726783752441406;-2.3512516021728516;-9.246891975402832;1.0
221 | -1.645749568939209;-2.028752565383911;-9.255855560302734;1.0
222 | -1.9071063995361328;-2.963960647583008;-9.242005348205566;1.0
223 | -1.8656647205352783;-3.18147349357605;-9.25041675567627;1.0
224 | -1.7651901245117188;-3.1438541412353516;-9.261210441589355;1.0
225 | -1.6590218544006348;-3.0419628620147705;-9.271562576293945;1.0
226 | -1.454249382019043;-2.7042999267578125;-9.2891263961792;1.0
227 | -1.3160767555236816;-2.487891912460327;-9.301172256469727;1.0
228 | -1.0872290134429932;-1.9470248222351074;-9.318024635314941;1.0
229 | -1.211350440979004;-2.56674861907959;-9.314431190490723;1.0
230 | -1.2824950218200684;-3.0408036708831787;-9.314390182495117;1.0
231 | -1.3785035610198975;-3.384348154067993;-9.309301376342773;1.0
232 | -1.4605293273925781;-3.707122325897217;-9.305452346801758;1.0
233 | -1.5788099765777588;-4.027937889099121;-9.297443389892578;1.0
234 | -1.7423546314239502;-4.3936614990234375;-9.28504753112793;1.0
235 | -1.9662961959838867;-4.5365400314331055;-9.261991500854492;1.0
236 | -2.133584976196289;-4.505965709686279;-9.242433547973633;1.0
237 | -2.220651149749756;-4.378552436828613;-9.23036003112793;1.0
238 | -2.226200580596924;-4.208187580108643;-9.226835250854492;1.0
239 | -2.2354254722595215;-4.065610408782959;-9.22336196899414;1.0
240 | -2.194772243499756;-3.9494102001190186;-9.226014137268066;1.0
241 | -2.1145501136779785;-3.8525712490081787;-9.233498573303223;1.0
242 | -1.9837307929992676;-3.6917381286621094;-9.245652198791504;1.0
243 | -1.9055280685424805;-3.6313867568969727;-9.253525733947754;1.0
244 | -1.7544536590576172;-3.529770612716675;-9.268990516662598;1.0
245 | -1.5873806476593018;-3.370896816253662;-9.285304069519043;1.0
246 | -1.3930609226226807;-3.2608556747436523;-9.305546760559082;1.0
247 | -1.2066700458526611;-3.062126636505127;-9.323381423950195;1.0
248 | -1.0425496101379395;-2.8406641483306885;-9.338294982910156;1.0
249 | -0.8627893924713135;-2.6071317195892334;-9.354782104492188;1.0
250 | -0.7189228534698486;-2.326450824737549;-9.366385459899902;1.0
251 | -0.17422866821289062;-0.948042094707489;-9.404947280883789;1.0
252 | -0.45698994398117065;-1.5355055332183838;-9.382752418518066;1.0
253 | -0.7181216478347778;-1.5773496627807617;-9.353748321533203;1.0
254 | 0.36136531829833984;-1.3580451011657715;-9.472862243652344;1.0
255 | -0.43104231357574463;-1.5304510593414307;-9.385618209838867;1.0
256 | -0.5728224515914917;-2.198732614517212;-9.380840301513672;1.0
257 | -0.62645423412323;-2.858865976333618;-9.385953903198242;1.0
258 | -0.5513516664505005;-2.970564365386963;-9.396397590637207;1.0
259 | -0.4155588150024414;-2.8358314037323;-9.409561157226562;1.0
260 | -0.33000385761260986;-2.719906806945801;-9.417326927185059;1.0
261 | -0.2703949511051178;-2.6090385913848877;-9.422226905822754;1.0
262 | -0.20912954211235046;-2.506868600845337;-9.427464485168457;1.0
263 | -0.043351560831069946;-2.2941083908081055;-9.442712783813477;1.0
264 | 0.40987735986709595;-0.9064469933509827;-9.470710754394531;1.0
265 | -0.18938341736793518;-2.8459131717681885;-9.435471534729004;1.0
266 | 0.024905383586883545;-2.1815545558929443;-9.448569297790527;1.0
267 | 0.17468202114105225;-2.026050329208374;-9.462968826293945;1.0
268 | 0.31451159715652466;-1.818342924118042;-9.47535228729248;1.0
269 | 0.4882160425186157;-1.6942715644836426;-9.493011474609375;1.0
270 | 0.6216304898262024;-1.6412124633789062;-9.507291793823242;1.0
271 | 0.677054226398468;-1.8379542827606201;-9.516942024230957;1.0
272 | 0.5784513354301453;-2.0737242698669434;-9.509726524353027;1.0
273 | 0.488498330116272;-2.307809352874756;-9.503467559814453;1.0
274 | 0.40387946367263794;-2.522808313369751;-9.497492790222168;1.0
275 | 0.40575110912323;-2.7209596633911133;-9.50107192993164;1.0
276 | 0.5215057730674744;-2.7164576053619385;-9.514167785644531;1.0
277 | 0.614052414894104;-2.590148687362671;-9.522553443908691;1.0
278 | 0.7378815412521362;-2.439699172973633;-9.534089088439941;1.0
279 | 0.8756937980651855;-2.2684788703918457;-9.546862602233887;1.0
280 | 0.9998824596405029;-2.0728416442871094;-9.557670593261719;1.0
281 | 1.0837806463241577;-1.9482178688049316;-9.565098762512207;1.0
282 | 1.1411552429199219;-1.684385061264038;-9.567145347595215;1.0
283 | 1.2467503547668457;-1.4382297992706299;-9.574979782104492;1.0
284 | 1.0550932884216309;-2.080134153366089;-9.564077377319336;1.0
285 | 1.0060062408447266;-2.387468099594116;-9.563713073730469;1.0
286 | 0.9938951730728149;-2.6063897609710693;-9.566055297851562;1.0
287 | 1.101000189781189;-2.603573799133301;-9.578195571899414;1.0
288 | 1.236793041229248;-2.468839645385742;-9.591358184814453;1.0
289 | 1.3795783519744873;-2.323720693588257;-9.605141639709473;1.0
290 | 1.4864695072174072;-2.131453514099121;-9.614038467407227;1.0
291 | 1.5950191020965576;-1.947887659072876;-9.623270988464355;1.0
292 | 1.696214199066162;-1.819892406463623;-9.632612228393555;1.0
293 | 1.7368667125701904;-1.7036924362182617;-9.63526439666748;1.0
294 | 1.8555073738098145;-1.3376917839050293;-9.642546653747559;1.0
295 | 1.6737968921661377;-2.0317983627319336;-9.633662223815918;1.0
296 | 1.5828287601470947;-2.8255324363708496;-9.636796951293945;1.0
297 | 1.459789514541626;-3.309694528579712;-9.631022453308105;1.0
298 | 1.3135437965393066;-3.6720521450042725;-9.620536804199219;1.0
299 | 1.062932014465332;-3.9103617668151855;-9.596068382263184;1.0
300 | 0.9138780832290649;-3.9754912853240967;-9.580212593078613;1.0
301 | 0.8516762852668762;-3.9785852432250977;-9.573185920715332;1.0
302 | 0.7605712413787842;-3.924142360687256;-9.56189250946045;1.0
303 | 0.6878494024276733;-3.730771064758301;-9.550333023071289;1.0
304 | 0.6913102269172668;-3.513535737991333;-9.547036170959473;1.0
305 | 0.8038968443870544;-3.2569942474365234;-9.555487632751465;1.0
306 | 0.977962851524353;-3.087735414505005;-9.572420120239258;1.0
307 | 1.1557036638259888;-2.890690565109253;-9.589298248291016;1.0
308 | 1.7410385608673096;-2.4788947105407715;-9.648910522460938;1.0
309 | 1.9437923431396484;-2.1777195930480957;-9.66686725616455;1.0
310 | 2.183522939682007;-1.7881312370300293;-9.68752670288086;1.0
311 | 2.4156839847564697;-1.2646641731262207;-9.705050468444824;1.0
312 | 2.149569272994995;-2.3632209300994873;-9.693435668945312;1.0
313 | 2.3601796627044678;-1.726646900177002;-9.706585884094238;1.0
314 | 2.5555830001831055;-1.4810454845428467;-9.724648475646973;1.0
315 | 2.712709903717041;-1.2699685096740723;-9.738943099975586;1.0
316 | 2.901695728302002;-1.1790134906768799;-9.758903503417969;1.0
317 | 2.9723992347717285;-1.4088730812072754;-9.770853996276855;1.0
318 | 2.8927536010742188;-1.6499738693237305;-9.765888214111328;1.0
319 | 2.7834835052490234;-1.9239158630371094;-9.75810718536377;1.0
320 | 2.7018179893493652;-2.201502561569214;-9.753530502319336;1.0
321 | 3.004255771636963;-1.5289955139160156;-9.776521682739258;1.0
322 | 3.1856751441955566;-1.304163932800293;-9.79334545135498;1.0
323 | 3.3597402572631836;-1.1349048614501953;-9.810276985168457;1.0
324 | 3.4445743560791016;-1.1093559265136719;-9.819497108459473;1.0
325 | 3.4313793182373047;-1.4638381004333496;-9.824019432067871;1.0
326 | 3.3151187896728516;-1.748166561126709;-9.815620422363281;1.0
327 | 3.2314348220825195;-2.062241554260254;-9.811432838439941;1.0
328 | 3.2805886268615723;-2.1789934635162354;-9.819011688232422;1.0
329 | 3.427626609802246;-2.1503520011901855;-9.835257530212402;1.0
330 | 3.495882987976074;-2.037797451019287;-9.841111183166504;1.0
331 | 3.656686782836914;-1.7989351749420166;-9.855351448059082;1.0
332 | 3.8338537216186523;-1.4576256275177002;-9.869714736938477;1.0
333 | 3.9913411140441895;-1.2013614177703857;-9.883280754089355;1.0
334 | 4.093261241912842;-0.9829919934272766;-9.891167640686035;1.0
335 | 4.2323689460754395;-0.8656607866287231;-9.905004501342773;1.0
336 | 4.303580284118652;-0.8156949281692505;-9.912260055541992;1.0
337 | 4.237342357635498;-0.891761839389801;-9.906013488769531;1.0
338 | 4.207425594329834;-1.3938777446746826;-9.911141395568848;1.0
339 | 4.133327960968018;-1.8053436279296875;-9.909701347351074;1.0
340 | 4.086979866027832;-1.9858171939849854;-9.907492637634277;1.0
341 | 3.888986587524414;-2.123642683029175;-9.887303352355957;1.0
342 | 3.759608745574951;-2.103728771209717;-9.87224292755127;1.0
343 | 3.7084364891052246;-2.0234625339508057;-9.865056037902832;1.0
344 | 3.784982204437256;-1.954411268234253;-9.872593879699707;1.0
345 | 3.9031152725219727;-1.8682351112365723;-9.88457202911377;1.0
346 | 4.10442590713501;-1.7478091716766357;-9.905433654785156;1.0
347 | 4.3250532150268555;-1.5875272750854492;-9.927816390991211;1.0
348 | 4.448519229888916;-1.482264757156372;-9.940078735351562;1.0
349 | 4.5916666984558105;-1.2919600009918213;-9.95313549041748;1.0
350 | 4.703890323638916;-1.080605387687683;-9.96231460571289;1.0
351 |
--------------------------------------------------------------------------------
/documentation/ModchartVariables.txt:
--------------------------------------------------------------------------------
1 | DrunkXModifier, DrunkYModifier, DrunkZModifier
2 |
3 | TipsyXModifier, TipsyYModifier, TipsyZModifier
4 |
5 | ReverseModifier, IncomingAngleModifier, RotateModifier, StrumLineRotateModifier, (the last 3 ones works with [X Y Z, for StrumLine IncomingAngle and Rotate] [rotatePointX and rotatePointY, for Rotate and StrumLine])
6 |
7 | BumpyModifier,
8 |
9 | XModifier, YModifier, ZModifier, ConfusionModifier,
10 |
11 | ScaleModifier, ScaleXModifier, ScaleYModifier,
12 |
13 | SkewModifier, SkewYModifier, SkewXModifier, SpeedModifier,
14 |
15 | StealthModifier, NoteStealthModifier, InvertModifier, FlipModifier,
16 |
17 | MiniModifier, ShrinkModifier, BeatXModifier, BeatYModifier, BeatZModifier,
18 |
19 | BounceXModifier, BounceYModifier, BounceZModifier,
20 |
21 | EaseCurveModifier, EaseCurveXModifier, EaseCurveYModifier, EaseCurveZModifier, EaseCurveAngleModifier,
22 |
23 | InvertSineModifier, BoostModifier, BrakeModifier, JumpModifier
24 |
25 | --some shits added by me (ed) lmao
26 |
27 | WaveXModifier, WaveYModifier, WaveZModifier,
28 |
29 | TimeStopModifier, StrumAngleModifier, JumpTargetModifier, JumpNotesModifier,
30 |
31 | LaneStealthModifier, EaseXModifier, HiddenModifier, SuddenModifier, NotesModifier, TargetsModifier
32 |
33 | --To move betwen center right and left i show you this shits
34 | MIDSCROLL:
35 |
36 | 340 for right
37 | -340 for left
38 | 0 to center again
39 |
40 | RIGHTSCROLL:
41 |
42 | -370 to center
43 | -670 to left
44 | 0 to right
45 |
46 | --FOR OPONNENT
47 |
48 | MIDSCROLL:
49 |
50 | 340 for center (0,1 strumLines)
51 | -340 for center (2,3 strumLines)
52 | 665 for right (0,1 strumLines)
53 | -665 for left (2,3 strumLines)
54 | 0 to original again
55 |
56 | RIGHTSCROLL:
57 |
58 | 370 to center
59 | 670 to left
60 | 0 to right
61 |
62 | --------------MODCHART VARS----------------
63 | startMod(name,modClass,type,pf) --To start a modifier
64 |
65 | setMod(name, value) --set a variable for the modifier
66 |
67 | setSubMod(name, subValName,value) --A submodifier variable
68 |
69 | setModTargetLane(name, value) --Strum Specific modifier value
70 |
71 | setModPlayfield(name,value) --Extra line value
72 |
73 | addPlayfield(x,y,z) --Add a extra line
74 |
75 | removePlayfield(idx) --Remove a extra line
76 |
77 | tweenModifier(modifier,val,time,ease) --do a modifier with a tween in seconds
78 |
79 | tweenModifierSubValue(modifier,subValue,val,time,ease) --do a modifier with a subValue
80 |
81 | setModEaseFunc(name,ease) --A mod ease with a value
82 |
83 | set(beat, argsAsString) --Add a working variable in a beat
84 |
85 | ease(beat, time, easeStr, argsAsString) --Add a working variable with movement in a beat
86 | --------------APPLY A MODCHART--------------
87 | startMod('Whatever','BoostModifier','',0) --'modName','modifiername','lines(strumsToApply, player, opponent, custom, leave [""] for all, playfield 0 = default playfield
88 |
89 | --start time, ease time, ease, modifier data (value, name)
90 | ease(beat, 2, 'expoOut', [[
91 | 0.5, DrunkY,
92 | ]])
93 | --Notes moves funky and cool, sustains also do curve effect
94 |
95 | --Check example for more info about this lmao -Ed
96 | --------------SOME CHANGES SHITS LMAO----------------
97 | ModName:speed
98 | ModName:x
99 | ModName:y
100 | ModName:z
101 | ModName:rotatePointX
102 | ModName:rotatePointY
103 | ---------------LANES YOU CAN USE-------------
104 | case 'player':
105 | PLAYERONLY;
106 |
107 | case 'opponent':
108 | OPPONENTONLY;
109 |
110 | case 'lane' | 'lanespecific':
111 | LANESPECIFIC;
112 | --------------DIFERENCE BETWEN HX AND LUA CUSTOM MODIFIERS-----------------
113 | --LUA
114 | game.playfieldRenderer.modifiers.get("customModTest").math
115 |
116 | --HX
117 | mod.math
--------------------------------------------------------------------------------
/examples/customPath.txt:
--------------------------------------------------------------------------------
1 | -5.32266902923584;1.5246357917785645;-8.777054786682129;1.0
2 | -5.234609603881836;1.7484805583953857;-8.783271789550781;1.0
3 | -4.900301456451416;2.3798604011535645;-8.810586929321289;1.0
4 | -4.539057731628418;2.6687521934509277;-8.846787452697754;1.0
5 | -3.8826723098754883;2.9988062381744385;-8.915874481201172;1.0
6 | -3.499480724334717;3.0214765071868896;-8.959095001220703;1.0
7 | -3.3510608673095703;2.920449733734131;-8.977700233459473;1.0
8 | -3.23814058303833;2.734546661376953;-8.9937105178833;1.0
9 | -3.2129225730895996;2.4665908813476562;-9.00113296508789;1.0
10 | -3.3027024269104004;2.1242594718933105;-8.996732711791992;1.0
11 | -3.628297805786133;1.5280909538269043;-8.969809532165527;1.0
12 | -3.9624013900756836;1.1121773719787598;-8.938857078552246;1.0
13 | -4.432987213134766;0.7346479296684265;-8.89172077178955;1.0
14 | -4.989719390869141;0.47027212381362915;-8.832858085632324;1.0
15 | -5.33845329284668;0.40233945846557617;-8.794328689575195;1.0
16 | -5.050148010253906;0.45850127935409546;-8.82618236541748;1.0
17 | -5.029303073883057;0.5452755093574524;-8.827080726623535;1.0
18 | -4.391894817352295;2.143267869949341;-8.872462272644043;1.0
19 | -4.3830060958862305;2.175076484680176;-8.872934341430664;1.0
20 | -5.2553277015686035;0.3583762049674988;-8.804534912109375;1.0
21 | -5.1723856925964355;-0.4300546944141388;-8.82736873626709;1.0
22 | -5.1723856925964355;-0.4300546944141388;-8.82736873626709;1.0
23 | -5.05217981338501;0.43756574392318726;-8.826306343078613;1.0
24 | -4.981097221374512;0.47317057847976685;-8.83379077911377;1.0
25 | -4.445980548858643;0.7297149300575256;-8.890326499938965;1.0
26 | -4.422902584075928;0.6993982195854187;-8.893467903137207;1.0
27 | -4.289186954498291;0.33815646171569824;-8.914822578430176;1.0
28 | -3.974761962890625;-0.13148707151412964;-8.95858383178711;1.0
29 | -3.7403483390808105;-0.294700026512146;-8.988033294677734;1.0
30 | -3.6869254112243652;-0.2799406349658966;-8.993861198425293;1.0
31 | -3.5333566665649414;0.07199054956436157;-9.005355834960938;1.0
32 | -3.3668928146362305;0.2654244303703308;-9.021012306213379;1.0
33 | -3.148952007293701;0.4384259581565857;-9.042874336242676;1.0
34 | -2.9370603561401367;0.688578188419342;-9.062736511230469;1.0
35 | -2.8379602432250977;0.8949999213218689;-9.070507049560547;1.0
36 | -2.75022554397583;1.138371467590332;-9.07635498046875;1.0
37 | -2.7764339447021484;1.2986266613006592;-9.070649147033691;1.0
38 | -2.8319082260131836;1.3400392532348633;-9.06363296508789;1.0
39 | -2.9218978881835938;1.3355627059936523;-9.053467750549316;1.0
40 | -3.004868507385254;1.2715349197387695;-9.045114517211914;1.0
41 | -3.1828699111938477;1.093257188796997;-9.027887344360352;1.0
42 | -3.3691816329956055;0.7088391184806824;-9.013216972351074;1.0
43 | -3.422018527984619;0.3504212498664856;-9.01329517364502;1.0
44 | -3.3937621116638184;0.13399535417556763;-9.020188331604004;1.0
45 | -3.328347682952881;0.08581626415252686;-9.028450965881348;1.0
46 | -3.1835060119628906;0.07486605644226074;-9.045119285583496;1.0
47 | -2.993687152862549;0.16841357946395874;-9.065130233764648;1.0
48 | -2.8458547592163086;0.32340675592422485;-9.079319953918457;1.0
49 | -2.653045654296875;0.5828946232795715;-9.09685230255127;1.0
50 | -2.5239481925964355;0.7908092141151428;-9.108009338378906;1.0
51 | -2.2325916290283203;1.3958618640899658;-9.130884170532227;1.0
52 | -2.1974499225616455;1.4157617092132568;-9.13454532623291;1.0
53 | -2.442473888397217;0.7718679308891296;-9.11760425567627;1.0
54 | -2.5173850059509277;0.256844162940979;-9.117829322814941;1.0
55 | -2.412655830383301;0.2293778657913208;-9.13021469116211;1.0
56 | -2.3232898712158203;0.25984084606170654;-9.139866828918457;1.0
57 | -2.179804801940918;0.39222943782806396;-9.153944969177246;1.0
58 | -2.002357244491577;0.709648072719574;-9.168745040893555;1.0
59 | -1.702239751815796;1.4730639457702637;-9.189926147460938;1.0
60 | -1.635328769683838;1.507857322692871;-9.196949005126953;1.0
61 | -1.62910795211792;1.452498435974121;-9.198596954345703;1.0
62 | -1.8891115188598633;0.7055982947349548;-9.181700706481934;1.0
63 | -1.865096092224121;0.3752055764198303;-9.190047264099121;1.0
64 | -1.7820234298706055;0.3478724956512451;-9.199965476989746;1.0
65 | -1.7135133743286133;0.37427324056625366;-9.207313537597656;1.0
66 | -1.570199966430664;0.48486971855163574;-9.221742630004883;1.0
67 | -1.4240710735321045;0.7396168112754822;-9.23404312133789;1.0
68 | -1.1689012050628662;1.1940202713012695;-9.255358695983887;1.0
69 | -1.050473690032959;1.5260505676269531;-9.26319408416748;1.0
70 | -1.0765066146850586;1.7080979347229004;-9.2571382522583;1.0
71 | -1.1446678638458252;1.7252795696258545;-9.249089241027832;1.0
72 | -1.2324354648590088;1.6864259243011475;-9.239762306213379;1.0
73 | -1.2838106155395508;1.615495204925537;-9.235121726989746;1.0
74 | -1.3679986000061035;1.398923397064209;-9.229220390319824;1.0
75 | -1.3923673629760742;1.163543939590454;-9.230446815490723;1.0
76 | -1.3569157123565674;0.9093559384346008;-9.238801002502441;1.0
77 | -1.279334306716919;0.8200300335884094;-9.249147415161133;1.0
78 | -1.154201865196228;0.8444053530693054;-9.262971878051758;1.0
79 | -1.0420336723327637;0.9141233563423157;-9.274552345275879;1.0
80 | -0.8950022459030151;1.0733113288879395;-9.288578987121582;1.0
81 | -0.7072662115097046;1.4275479316711426;-9.303923606872559;1.0
82 | -0.5383337736129761;1.7215492725372314;-9.31815242767334;1.0
83 | -0.39519548416137695;1.8103539943695068;-9.332931518554688;1.0
84 | -0.33005672693252563;1.8317453861236572;-9.339981079101562;1.0
85 | -0.25195416808128357;1.8077962398529053;-9.349276542663574;1.0
86 | -0.21208593249320984;1.6893668174743652;-9.35582447052002;1.0
87 | -0.2257145494222641;1.443023920059204;-9.35845947265625;1.0
88 | -0.3607226014137268;1.0163805484771729;-9.350346565246582;1.0
89 | -0.4754299521446228;0.7329409718513489;-9.342108726501465;1.0
90 | -0.6449167132377625;0.578081488609314;-9.32545280456543;1.0
91 | -0.7376539707183838;0.5426102876663208;-9.315503120422363;1.0
92 | -0.8489514589309692;0.5818514823913574;-9.302170753479004;1.0
93 | -0.878355860710144;0.758889377117157;-9.295815467834473;1.0
94 | -0.8644500970840454;0.9356613755226135;-9.294394493103027;1.0
95 | -0.8468254804611206;1.161024570465088;-9.292571067810059;1.0
96 | -0.8468254804611206;1.161024570465088;-9.292571067810059;1.0
97 | -0.7261083126068115;1.0496416091918945;-9.308199882507324;1.0
98 | -0.7112677097320557;0.9263364672660828;-9.31198501586914;1.0
99 | -0.633686363697052;0.8370113968849182;-9.322330474853516;1.0
100 | -0.5215896964073181;0.7935743927955627;-9.33582592010498;1.0
101 | -0.31783077120780945;0.8593752980232239;-9.357893943786621;1.0
102 | -0.10308815538883209;1.0491602420806885;-9.379106521606445;1.0
103 | 0.11527067422866821;1.3789005279541016;-9.398353576660156;1.0
104 | 0.3083258867263794;1.7733361721038818;-9.413619995117188;1.0
105 | 0.3854227662086487;1.936307430267334;-9.419624328613281;1.0
106 | 0.3845199942588806;2.0318660736083984;-9.41789722442627;1.0
107 | 0.40919923782348633;1.9931573867797852;-9.42136287689209;1.0
108 | 0.45660877227783203;1.8805487155914307;-9.428672790527344;1.0
109 | 0.5648127794265747;1.7667279243469238;-9.44291877746582;1.0
110 | 0.56011962890625;1.700540542602539;-9.443509101867676;1.0
111 | 0.3671293258666992;0.8970697522163391;-9.435200691223145;1.0
112 | 0.4065456986427307;0.8264201283454895;-9.440886497497559;1.0
113 | 0.5124216079711914;0.8383412957191467;-9.45273208618164;1.0
114 | 0.5950434803962708;0.858787477016449;-9.461787223815918;1.0
115 | 0.9431252479553223;1.3704533576965332;-9.492703437805176;1.0
116 | 1.0598821640014648;1.5977203845977783;-9.502127647399902;1.0
117 | 1.4972403049468994;2.9213738441467285;-9.529407501220703;1.0
118 | 1.5103371143341064;2.9343698024749756;-9.530677795410156;1.0
119 | 0.9662704467773438;0.9311016201972961;-9.502802848815918;1.0
120 | 0.9534022808074951;0.9259839653968811;-9.501425743103027;1.0
121 | 0.9314626455307007;0.93215411901474;-9.498824119567871;1.0
122 | 0.9314626455307007;0.93215411901474;-9.498824119567871;1.0
123 | 1.1842787265777588;1.6759123802185059;-9.5149564743042;1.0
124 | 1.4127733707427979;2.00240421295166;-9.535408973693848;1.0
125 | 1.609025001525879;2.171180486679077;-9.554875373840332;1.0
126 | 1.7691943645477295;2.2023813724517822;-9.572571754455566;1.0
127 | 1.8297145366668701;2.020961046218872;-9.582541465759277;1.0
128 | 1.7647697925567627;1.8986501693725586;-9.577229499816895;1.0
129 | 1.5185906887054443;1.6104891300201416;-9.554110527038574;1.0
130 | 1.3787741661071777;1.4997029304504395;-9.540082931518555;1.0
131 | 1.3916633129119873;1.4865474700927734;-9.541773796081543;1.0
132 | 1.4837167263031006;1.2486069202423096;-9.556291580200195;1.0
133 | 1.6066365242004395;1.1211166381835938;-9.5724458694458;1.0
134 | 1.7032382488250732;1.0772719383239746;-9.584182739257812;1.0
135 | 1.8228232860565186;1.1580073833465576;-9.596420288085938;1.0
136 | 2.0222456455230713;1.47361421585083;-9.613750457763672;1.0
137 | 2.0773041248321533;1.4843401908874512;-9.619833946228027;1.0
138 | 2.189255475997925;1.3599352836608887;-9.634688377380371;1.0
139 | 2.350801944732666;1.438401460647583;-9.651739120483398;1.0
140 | 2.6131649017333984;1.7506022453308105;-9.676289558410645;1.0
141 | 2.7996997833251953;2.079364538192749;-9.691929817199707;1.0
142 | 2.8237266540527344;2.334696054458618;-9.690325736999512;1.0
143 | 2.788565158843994;2.4375061988830566;-9.684577941894531;1.0
144 | 2.7406396865844727;2.443836212158203;-9.67901611328125;1.0
145 | 2.6755714416503906;2.4311606884002686;-9.67182731628418;1.0
146 | 2.536923885345459;2.341489553451538;-9.657572746276855;1.0
147 | 2.29437255859375;2.007037401199341;-9.63565444946289;1.0
148 | 2.171407461166382;1.7533199787139893;-9.625971794128418;1.0
149 | 2.1400363445281982;1.4547853469848633;-9.627476692199707;1.0
150 | 2.1939661502838135;1.1989738941192627;-9.637959480285645;1.0
151 | 2.353717803955078;1.1778738498687744;-9.65649700164795;1.0
152 | 2.6263413429260254;1.2727558612823486;-9.685907363891602;1.0
153 | 2.9553589820861816;1.6710479259490967;-9.716582298278809;1.0
154 | 3.000405788421631;1.679823875427246;-9.721559524536133;1.0
155 | 2.9933981895446777;1.5531325340270996;-9.72291374206543;1.0
156 | 3.02059268951416;1.3286681175231934;-9.729823112487793;1.0
157 | 3.1324172019958496;1.3138971328735352;-9.742798805236816;1.0
158 | 3.3282508850097656;1.4303734302520752;-9.763105392456055;1.0
159 | 3.501059055328369;1.6676909923553467;-9.778738975524902;1.0
160 | 3.5897412300109863;1.8833961486816406;-9.785164833068848;1.0
161 | 3.694146156311035;2.3162624835968018;-9.789690017700195;1.0
162 | 3.6840972900390625;2.5597355365753174;-9.784409523010254;1.0
163 | 3.577275276184082;2.575479507446289;-9.77198600769043;1.0
164 | 3.3922033309936523;2.4297685623168945;-9.753402709960938;1.0
165 | 3.193948268890381;2.1352765560150146;-9.735844612121582;1.0
166 | 3.0453295707702637;1.7982337474822998;-9.724658966064453;1.0
167 | 3.0030760765075684;1.6385674476623535;-9.722563743591309;1.0
168 | 3.007911205291748;1.367973804473877;-9.72771167755127;1.0
169 | 3.100468158721924;1.3181183338165283;-9.739092826843262;1.0
170 | 3.1865158081054688;1.3296592235565186;-9.748687744140625;1.0
171 | 3.3563642501831055;1.4462940692901611;-9.766033172607422;1.0
172 | 3.5131988525390625;1.685720682144165;-9.779813766479492;1.0
173 | 4.116020202636719;3.453263759613037;-9.818379402160645;1.0
174 | 3.652557849884033;1.9896275997161865;-9.790508270263672;1.0
175 | 3.6366610527038574;1.5008947849273682;-9.797003746032715;1.0
176 | 3.6822500228881836;1.4523355960845947;-9.803016662597656;1.0
177 | 3.757538318634033;1.493109941482544;-9.810890197753906;1.0
178 | 3.854224681854248;1.5850520133972168;-9.820331573486328;1.0
179 | 4.037461757659912;1.8766188621520996;-9.83622932434082;1.0
180 | 4.1816182136535645;2.1553494930267334;-9.847896575927734;1.0
181 | 4.156808376312256;1.4315543174743652;-9.857372283935547;1.0
182 | 3.0348057746887207;0.9790293574333191;-9.737380981445312;1.0
183 | -1.1645309925079346;0.2741355299949646;-9.27148723602295;1.0
184 | -3.966914653778076;-0.554682731628418;-8.966667175292969;1.0
185 | -5.333769798278809;-2.132967233657837;-8.837940216064453;1.0
186 | -3.6712446212768555;-2.838393211364746;-9.039117813110352;1.0
187 | -2.976569652557373;-2.576744318008423;-9.113723754882812;1.0
188 | -2.170823097229004;-1.815215826034546;-9.192476272583008;1.0
189 | -1.8277311325073242;-1.0265085697174072;-9.218117713928223;1.0
190 | -1.781813144683838;-0.4671350121498108;-9.213837623596191;1.0
191 | -1.951695442199707;-0.3287825584411621;-9.192154884338379;1.0
192 | -2.1326065063476562;-0.2737894058227539;-9.170633316040039;1.0
193 | -2.383432388305664;-0.32264968752861023;-9.14292049407959;1.0
194 | -3.0035791397094727;-0.551734209060669;-9.076240539550781;1.0
195 | -3.3513498306274414;-0.8450651168823242;-9.04164981842041;1.0
196 | -3.7364578247070312;-1.2719969749450684;-9.005081176757812;1.0
197 | -3.8871021270751953;-1.7525136470794678;-8.996102333068848;1.0
198 | -3.1969618797302246;-0.7608497142791748;-9.057788848876953;1.0
199 | -2.5893545150756836;-0.37178659439086914;-9.120321273803711;1.0
200 | -1.9719481468200684;-0.269563764333725;-9.188843727111816;1.0
201 | -1.7769865989685059;-0.7278742790222168;-9.218816757202148;1.0
202 | -1.9574003219604492;-1.4758691787719727;-9.210996627807617;1.0
203 | -2.7033262252807617;-2.315976619720459;-9.140387535095215;1.0
204 | -3.2054858207702637;-2.6935245990753174;-9.089658737182617;1.0
205 | -3.5897250175476074;-2.7954421043395996;-9.047664642333984;1.0
206 | -2.880189895629883;-1.1051981449127197;-9.099687576293945;1.0
207 | -3.6013293266296387;-2.7345387935638428;-9.045309066772461;1.0
208 | -3.725451946258545;-3.3542640209198;-9.041714668273926;1.0
209 | -3.719327449798584;-3.6688919067382812;-9.047758102416992;1.0
210 | -3.622664451599121;-2.810882806777954;-9.04417896270752;1.0
211 | -3.3262133598327637;-2.6719236373901367;-9.075553894042969;1.0
212 | -3.0164999961853027;-2.602569103240967;-9.109619140625;1.0
213 | -2.9075231552124023;-2.7979037761688232;-9.125337600708008;1.0
214 | -2.773679733276367;-3.123744010925293;-9.146106719970703;1.0
215 | -2.537705421447754;-3.420666456222534;-9.17800521850586;1.0
216 | -2.2643957138061523;-3.583988904953003;-9.211881637573242;1.0
217 | -1.9039382934570312;-3.2160000801086426;-9.246648788452148;1.0
218 | -1.9124400615692139;-2.9830470085144043;-9.24172306060791;1.0
219 | -1.8530457019805908;-2.6827266216278076;-9.243378639221191;1.0
220 | -1.7726783752441406;-2.3512516021728516;-9.246891975402832;1.0
221 | -1.645749568939209;-2.028752565383911;-9.255855560302734;1.0
222 | -1.9071063995361328;-2.963960647583008;-9.242005348205566;1.0
223 | -1.8656647205352783;-3.18147349357605;-9.25041675567627;1.0
224 | -1.7651901245117188;-3.1438541412353516;-9.261210441589355;1.0
225 | -1.6590218544006348;-3.0419628620147705;-9.271562576293945;1.0
226 | -1.454249382019043;-2.7042999267578125;-9.2891263961792;1.0
227 | -1.3160767555236816;-2.487891912460327;-9.301172256469727;1.0
228 | -1.0872290134429932;-1.9470248222351074;-9.318024635314941;1.0
229 | -1.211350440979004;-2.56674861907959;-9.314431190490723;1.0
230 | -1.2824950218200684;-3.0408036708831787;-9.314390182495117;1.0
231 | -1.3785035610198975;-3.384348154067993;-9.309301376342773;1.0
232 | -1.4605293273925781;-3.707122325897217;-9.305452346801758;1.0
233 | -1.5788099765777588;-4.027937889099121;-9.297443389892578;1.0
234 | -1.7423546314239502;-4.3936614990234375;-9.28504753112793;1.0
235 | -1.9662961959838867;-4.5365400314331055;-9.261991500854492;1.0
236 | -2.133584976196289;-4.505965709686279;-9.242433547973633;1.0
237 | -2.220651149749756;-4.378552436828613;-9.23036003112793;1.0
238 | -2.226200580596924;-4.208187580108643;-9.226835250854492;1.0
239 | -2.2354254722595215;-4.065610408782959;-9.22336196899414;1.0
240 | -2.194772243499756;-3.9494102001190186;-9.226014137268066;1.0
241 | -2.1145501136779785;-3.8525712490081787;-9.233498573303223;1.0
242 | -1.9837307929992676;-3.6917381286621094;-9.245652198791504;1.0
243 | -1.9055280685424805;-3.6313867568969727;-9.253525733947754;1.0
244 | -1.7544536590576172;-3.529770612716675;-9.268990516662598;1.0
245 | -1.5873806476593018;-3.370896816253662;-9.285304069519043;1.0
246 | -1.3930609226226807;-3.2608556747436523;-9.305546760559082;1.0
247 | -1.2066700458526611;-3.062126636505127;-9.323381423950195;1.0
248 | -1.0425496101379395;-2.8406641483306885;-9.338294982910156;1.0
249 | -0.8627893924713135;-2.6071317195892334;-9.354782104492188;1.0
250 | -0.7189228534698486;-2.326450824737549;-9.366385459899902;1.0
251 | -0.17422866821289062;-0.948042094707489;-9.404947280883789;1.0
252 | -0.45698994398117065;-1.5355055332183838;-9.382752418518066;1.0
253 | -0.7181216478347778;-1.5773496627807617;-9.353748321533203;1.0
254 | 0.36136531829833984;-1.3580451011657715;-9.472862243652344;1.0
255 | -0.43104231357574463;-1.5304510593414307;-9.385618209838867;1.0
256 | -0.5728224515914917;-2.198732614517212;-9.380840301513672;1.0
257 | -0.62645423412323;-2.858865976333618;-9.385953903198242;1.0
258 | -0.5513516664505005;-2.970564365386963;-9.396397590637207;1.0
259 | -0.4155588150024414;-2.8358314037323;-9.409561157226562;1.0
260 | -0.33000385761260986;-2.719906806945801;-9.417326927185059;1.0
261 | -0.2703949511051178;-2.6090385913848877;-9.422226905822754;1.0
262 | -0.20912954211235046;-2.506868600845337;-9.427464485168457;1.0
263 | -0.043351560831069946;-2.2941083908081055;-9.442712783813477;1.0
264 | 0.40987735986709595;-0.9064469933509827;-9.470710754394531;1.0
265 | -0.18938341736793518;-2.8459131717681885;-9.435471534729004;1.0
266 | 0.024905383586883545;-2.1815545558929443;-9.448569297790527;1.0
267 | 0.17468202114105225;-2.026050329208374;-9.462968826293945;1.0
268 | 0.31451159715652466;-1.818342924118042;-9.47535228729248;1.0
269 | 0.4882160425186157;-1.6942715644836426;-9.493011474609375;1.0
270 | 0.6216304898262024;-1.6412124633789062;-9.507291793823242;1.0
271 | 0.677054226398468;-1.8379542827606201;-9.516942024230957;1.0
272 | 0.5784513354301453;-2.0737242698669434;-9.509726524353027;1.0
273 | 0.488498330116272;-2.307809352874756;-9.503467559814453;1.0
274 | 0.40387946367263794;-2.522808313369751;-9.497492790222168;1.0
275 | 0.40575110912323;-2.7209596633911133;-9.50107192993164;1.0
276 | 0.5215057730674744;-2.7164576053619385;-9.514167785644531;1.0
277 | 0.614052414894104;-2.590148687362671;-9.522553443908691;1.0
278 | 0.7378815412521362;-2.439699172973633;-9.534089088439941;1.0
279 | 0.8756937980651855;-2.2684788703918457;-9.546862602233887;1.0
280 | 0.9998824596405029;-2.0728416442871094;-9.557670593261719;1.0
281 | 1.0837806463241577;-1.9482178688049316;-9.565098762512207;1.0
282 | 1.1411552429199219;-1.684385061264038;-9.567145347595215;1.0
283 | 1.2467503547668457;-1.4382297992706299;-9.574979782104492;1.0
284 | 1.0550932884216309;-2.080134153366089;-9.564077377319336;1.0
285 | 1.0060062408447266;-2.387468099594116;-9.563713073730469;1.0
286 | 0.9938951730728149;-2.6063897609710693;-9.566055297851562;1.0
287 | 1.101000189781189;-2.603573799133301;-9.578195571899414;1.0
288 | 1.236793041229248;-2.468839645385742;-9.591358184814453;1.0
289 | 1.3795783519744873;-2.323720693588257;-9.605141639709473;1.0
290 | 1.4864695072174072;-2.131453514099121;-9.614038467407227;1.0
291 | 1.5950191020965576;-1.947887659072876;-9.623270988464355;1.0
292 | 1.696214199066162;-1.819892406463623;-9.632612228393555;1.0
293 | 1.7368667125701904;-1.7036924362182617;-9.63526439666748;1.0
294 | 1.8555073738098145;-1.3376917839050293;-9.642546653747559;1.0
295 | 1.6737968921661377;-2.0317983627319336;-9.633662223815918;1.0
296 | 1.5828287601470947;-2.8255324363708496;-9.636796951293945;1.0
297 | 1.459789514541626;-3.309694528579712;-9.631022453308105;1.0
298 | 1.3135437965393066;-3.6720521450042725;-9.620536804199219;1.0
299 | 1.062932014465332;-3.9103617668151855;-9.596068382263184;1.0
300 | 0.9138780832290649;-3.9754912853240967;-9.580212593078613;1.0
301 | 0.8516762852668762;-3.9785852432250977;-9.573185920715332;1.0
302 | 0.7605712413787842;-3.924142360687256;-9.56189250946045;1.0
303 | 0.6878494024276733;-3.730771064758301;-9.550333023071289;1.0
304 | 0.6913102269172668;-3.513535737991333;-9.547036170959473;1.0
305 | 0.8038968443870544;-3.2569942474365234;-9.555487632751465;1.0
306 | 0.977962851524353;-3.087735414505005;-9.572420120239258;1.0
307 | 1.1557036638259888;-2.890690565109253;-9.589298248291016;1.0
308 | 1.7410385608673096;-2.4788947105407715;-9.648910522460938;1.0
309 | 1.9437923431396484;-2.1777195930480957;-9.66686725616455;1.0
310 | 2.183522939682007;-1.7881312370300293;-9.68752670288086;1.0
311 | 2.4156839847564697;-1.2646641731262207;-9.705050468444824;1.0
312 | 2.149569272994995;-2.3632209300994873;-9.693435668945312;1.0
313 | 2.3601796627044678;-1.726646900177002;-9.706585884094238;1.0
314 | 2.5555830001831055;-1.4810454845428467;-9.724648475646973;1.0
315 | 2.712709903717041;-1.2699685096740723;-9.738943099975586;1.0
316 | 2.901695728302002;-1.1790134906768799;-9.758903503417969;1.0
317 | 2.9723992347717285;-1.4088730812072754;-9.770853996276855;1.0
318 | 2.8927536010742188;-1.6499738693237305;-9.765888214111328;1.0
319 | 2.7834835052490234;-1.9239158630371094;-9.75810718536377;1.0
320 | 2.7018179893493652;-2.201502561569214;-9.753530502319336;1.0
321 | 3.004255771636963;-1.5289955139160156;-9.776521682739258;1.0
322 | 3.1856751441955566;-1.304163932800293;-9.79334545135498;1.0
323 | 3.3597402572631836;-1.1349048614501953;-9.810276985168457;1.0
324 | 3.4445743560791016;-1.1093559265136719;-9.819497108459473;1.0
325 | 3.4313793182373047;-1.4638381004333496;-9.824019432067871;1.0
326 | 3.3151187896728516;-1.748166561126709;-9.815620422363281;1.0
327 | 3.2314348220825195;-2.062241554260254;-9.811432838439941;1.0
328 | 3.2805886268615723;-2.1789934635162354;-9.819011688232422;1.0
329 | 3.427626609802246;-2.1503520011901855;-9.835257530212402;1.0
330 | 3.495882987976074;-2.037797451019287;-9.841111183166504;1.0
331 | 3.656686782836914;-1.7989351749420166;-9.855351448059082;1.0
332 | 3.8338537216186523;-1.4576256275177002;-9.869714736938477;1.0
333 | 3.9913411140441895;-1.2013614177703857;-9.883280754089355;1.0
334 | 4.093261241912842;-0.9829919934272766;-9.891167640686035;1.0
335 | 4.2323689460754395;-0.8656607866287231;-9.905004501342773;1.0
336 | 4.303580284118652;-0.8156949281692505;-9.912260055541992;1.0
337 | 4.237342357635498;-0.891761839389801;-9.906013488769531;1.0
338 | 4.207425594329834;-1.3938777446746826;-9.911141395568848;1.0
339 | 4.133327960968018;-1.8053436279296875;-9.909701347351074;1.0
340 | 4.086979866027832;-1.9858171939849854;-9.907492637634277;1.0
341 | 3.888986587524414;-2.123642683029175;-9.887303352355957;1.0
342 | 3.759608745574951;-2.103728771209717;-9.87224292755127;1.0
343 | 3.7084364891052246;-2.0234625339508057;-9.865056037902832;1.0
344 | 3.784982204437256;-1.954411268234253;-9.872593879699707;1.0
345 | 3.9031152725219727;-1.8682351112365723;-9.88457202911377;1.0
346 | 4.10442590713501;-1.7478091716766357;-9.905433654785156;1.0
347 | 4.3250532150268555;-1.5875272750854492;-9.927816390991211;1.0
348 | 4.448519229888916;-1.482264757156372;-9.940078735351562;1.0
349 | 4.5916666984558105;-1.2919600009918213;-9.95313549041748;1.0
350 | 4.703890323638916;-1.080605387687683;-9.96231460571289;1.0
351 |
--------------------------------------------------------------------------------
/examples/leather/modchart.lua:
--------------------------------------------------------------------------------
1 | function createPost()
2 |
3 | --name, modifier class, type (defaults to all), playfield number (-1 = all)
4 | --other types:
5 | -- player
6 | -- opponent
7 | -- lane (needs to have its target lane set)
8 | startMod('reverse', 'ReverseModifier', '', -1)
9 |
10 | for i = 0,3 do
11 | local beat = i*8 --2 sections, loop 4x to last for 8 sections
12 |
13 | --start time, ease time, ease, modifier data (value, name)
14 | ease(beat, 2, 'expoOut', [[
15 | 1, reverse,
16 | 360, confusion
17 | ]])
18 | --reverse flips the scroll
19 | --confusion spins the notes
20 |
21 | --one section after
22 | ease((beat)+4, 2, 'expoOut', [[
23 | 0, reverse,
24 | 0, confusion
25 | ]])
26 | end
27 |
28 |
29 | startMod('drunkPF0', 'DrunkXModifier', '', 0) --playfield 0 = default playfield
30 | addPlayfield(0,0,0)
31 | startMod('zPF1', 'ZModifier', '', 1)
32 | startMod('tipsyPF1', 'TipsyYModifier', '', 1)
33 |
34 | ease(32, 4, 'cubeInOut', [[
35 | -300, zPF1,
36 | 1, tipsyPF1,
37 | 2, tipsyPF1:speed
38 | ]]) --puting ":" makes it ease a submod, in this case its changing the speed
39 |
40 |
41 | for i = 4,7 do
42 | local beat = i*8
43 |
44 | --start time, ease time, ease, modifier data (value, name)
45 | ease(beat, 1, 'expoOut', [[
46 | 1.5, drunkPF0,
47 | 4, drunkPF0:speed
48 | ]])
49 |
50 | --one section after
51 | ease((beat)+4, 1, 'expoOut', [[
52 | -1.5, drunkPF0
53 | ]])
54 | end
55 |
56 |
57 | startMod('customModTest', 'Modifier', '', -1)
58 |
59 | ease(64, 1, 'cubeInOut', [[
60 | 0, zPF1,
61 | 0, tipsyPF1,
62 | 0, drunkPF0,
63 | 1, customModTest
64 | ]])
65 | end
66 |
--------------------------------------------------------------------------------
/examples/leather/modifiers.hx:
--------------------------------------------------------------------------------
1 |
2 | //move notes and strums back a little
3 | PlayState.instance.playfieldRenderer.modifiers.get("customModTest").noteMath = function(noteData, lane, curPos, pf){
4 | noteData.z += PlayState.instance.playfieldRenderer.modifiers.get("customModTest").currentValue * -500;
5 | }
6 | PlayState.instance.playfieldRenderer.modifiers.get("customModTest").strumMath = function(noteData, lane, pf){
7 | noteData.z += PlayState.instance.playfieldRenderer.modifiers.get("customModTest").currentValue * -500;
8 | }
9 | //do crazy incoming angles
10 | PlayState.instance.playfieldRenderer.modifiers.get("customModTest").incomingAngleMath = function(lane, curPos, pf){
11 | var xAngle = 45*lane + curPos/30;
12 | var yAngle = 90*lane + curPos/7;
13 | var value = PlayState.instance.playfieldRenderer.modifiers.get("customModTest").currentValue;
14 | return [xAngle*value, yAngle*value];
15 | }
--------------------------------------------------------------------------------
/examples/modchart editor testing/fusion-reactor/customMods/IncomingAngleCurve.hx:
--------------------------------------------------------------------------------
1 | function initMod(mod)
2 | {
3 | mod.incomingAngleMath = function(lane, curPos, pf)
4 | {
5 | return [0, mod.currentValue*(curPos*0.015)];
6 | };
7 | }
--------------------------------------------------------------------------------
/examples/modchart editor testing/fusion-reactor/customMods/IncomingAngleSmooth.hx:
--------------------------------------------------------------------------------
1 | function initMod(mod)
2 | {
3 | mod.incomingAngleMath = function(lane, curPos, pf)
4 | {
5 | return [0, mod.currentValue+(curPos*0.015)];
6 | };
7 | }
--------------------------------------------------------------------------------
/examples/modchart editor testing/fusion-reactor/customMods/InvertIncomingAngle.hx:
--------------------------------------------------------------------------------
1 | function initMod(mod)
2 | {
3 | mod.incomingAngleMath = function(lane, curPos, pf)
4 | {
5 | if (lane % 2 == 0)
6 | {
7 | return [0, mod.currentValue+(curPos*0.015)];
8 | }
9 | return [0, -mod.currentValue-(curPos*0.015)];
10 | };
11 | }
--------------------------------------------------------------------------------
/examples/modchart editor testing/fusion-reactor/customMods/MoveYWaveShit.hx:
--------------------------------------------------------------------------------
1 | function initMod(mod)
2 | {
3 | mod.noteMath = function(noteData, lane, curPos, pf)
4 | {
5 | noteData.y += 260*Math.sin(((Conductor.songPosition+curPos)*0.0008)+(lane/4));
6 | };
7 | mod.strumMath = function(noteData, lane, pf)
8 | {
9 | noteData.y += 260*Math.sin((Conductor.songPosition*0.0008)+(lane/4));
10 | };
11 | }
--------------------------------------------------------------------------------
/examples/psych/script.lua:
--------------------------------------------------------------------------------
1 | function onCreatePost()
2 |
3 | --name, modifier class, type (defaults to all), playfield number (-1 = all)
4 | --other types:
5 | -- player
6 | -- opponent
7 | -- lane (needs to have its target lane set)
8 | startMod('reverse', 'ReverseModifier', '', -1)
9 |
10 | for i = 0,3 do
11 | local beat = i*8 --2 sections, loop 4x to last for 8 sections
12 |
13 | --start time, ease time, ease, modifier data (value, name)
14 | ease(beat, 2, 'expoOut', [[
15 | 1, reverse,
16 | 360, confusion
17 | ]])
18 | --reverse flips the scroll
19 | --confusion spins the notes
20 |
21 | --one section after
22 | ease((beat)+4, 2, 'expoOut', [[
23 | 0, reverse,
24 | 0, confusion
25 | ]])
26 | end
27 |
28 |
29 | startMod('drunkPF0', 'DrunkXModifier', '', 0) --playfield 0 = default playfield
30 | addPlayfield(0,0,0)
31 | startMod('zPF1', 'ZModifier', '', 1)
32 | startMod('tipsyPF1', 'TipsyYModifier', '', 1)
33 |
34 | ease(32, 4, 'cubeInOut', [[
35 | -300, zPF1,
36 | 1, tipsyPF1,
37 | 2, tipsyPF1:speed
38 | ]]) --puting ":" makes it ease a submod, in this case its changing the speed
39 |
40 |
41 | for i = 4,7 do
42 | local beat = i*8
43 |
44 | --start time, ease time, ease, modifier data (value, name)
45 | ease(beat, 1, 'expoOut', [[
46 | 1.5, drunkPF0,
47 | 4, drunkPF0:speed
48 | ]])
49 |
50 | --one section after
51 | ease((beat)+4, 1, 'expoOut', [[
52 | -1.5, drunkPF0
53 | ]])
54 | end
55 |
56 |
57 | startMod('customModTest', 'Modifier', '', -1)
58 |
59 | --you might get an error if you have luaDebugMode enabled, just ignore them lol it should still work
60 | runHaxeCode([[
61 |
62 | //move notes and strums back a little
63 | game.playfieldRenderer.modifiers.get("customModTest").noteMath = function(noteData, lane, curPos, pf)
64 | {
65 | noteData.z += game.playfieldRenderer.modifiers.get("customModTest").currentValue * -500;
66 | }
67 | game.playfieldRenderer.modifiers.get("customModTest").strumMath = function(noteData, lane, pf)
68 | {
69 | noteData.z += game.playfieldRenderer.modifiers.get("customModTest").currentValue * -500;
70 | }
71 |
72 | //do crazy incoming angles
73 | game.playfieldRenderer.modifiers.get("customModTest").incomingAngleMath = function(lane, curPos, pf)
74 | {
75 | var xAngle = 45*lane + curPos/30;
76 | var yAngle = 90*lane + curPos/7;
77 | var value = game.playfieldRenderer.modifiers.get("customModTest").currentValue;
78 | return [xAngle*value, yAngle*value];
79 | }
80 | ]])
81 |
82 | ease(64, 1, 'cubeInOut', [[
83 | 0, zPF1,
84 | 0, tipsyPF1,
85 | 0, drunkPF0,
86 | 1, customModTest
87 | ]])
88 | end
89 |
--------------------------------------------------------------------------------
/examples/readme.txt:
--------------------------------------------------------------------------------
1 | if you want a customPath name it "path" and put it inside customMods folder (inside a song) so it will load the path
2 |
3 | don't worry it won't crash if the path is not found but it will if path its wrong, check customPath for a better example
4 |
5 | -Edwhak
--------------------------------------------------------------------------------
/haxelib.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fnf-modcharting-tools",
3 | "url" : "https://github.com/EdwhakKB/FNF-Modcharting-Tools",
4 | "license": "Apache",
5 | "tags": ["fnf"],
6 | "description": "A modchart framework for Friday Night Funkin.",
7 | "version": "1.0.1",
8 | "classPath": "source/",
9 | "releasenote": "",
10 | "contributors": ["TheZoroForce240","UncertainProd","EdwhakKB","Vortex","Glowsoony"],
11 | "dependencies": {
12 | }
13 | }
--------------------------------------------------------------------------------
/include.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/readme/custommods.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EdwhakKB/FNF-Modcharting-Tools/47a411c67e7deaa39c4e29d8640c8b2f4e36ea7d/readme/custommods.gif
--------------------------------------------------------------------------------
/readme/modifiers.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EdwhakKB/FNF-Modcharting-Tools/47a411c67e7deaa39c4e29d8640c8b2f4e36ea7d/readme/modifiers.gif
--------------------------------------------------------------------------------
/readme/sustains.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/EdwhakKB/FNF-Modcharting-Tools/47a411c67e7deaa39c4e29d8640c8b2f4e36ea7d/readme/sustains.gif
--------------------------------------------------------------------------------
/source/flixel/addons/effects/FlxSkewedSprite.hx:
--------------------------------------------------------------------------------
1 | package flixel.addons.effects;
2 |
3 | import openfl.geom.Matrix;
4 | import flixel.FlxCamera;
5 | import flixel.FlxG;
6 | import flixel.FlxSprite;
7 | import flixel.graphics.frames.FlxFrame.FlxFrameAngle;
8 | import flixel.math.FlxAngle;
9 | import flixel.math.FlxPoint;
10 | import flixel.util.FlxDestroyUtil;
11 |
12 | /**
13 | * @author Zaphod
14 | */
15 | class FlxSkewedSprite extends FlxSprite
16 | {
17 |
18 | public var skew(default, null):FlxPoint = FlxPoint.get();
19 |
20 | public var skewOffset:Bool = false;
21 | public var flipSkew:Bool = false;
22 |
23 | /**
24 | * Tranformation matrix for this sprite.
25 | * Used only when matrixExposed is set to true
26 | */
27 | public var transformMatrix(default, null):Matrix = new Matrix();
28 |
29 | /**
30 | * Bool flag showing whether transformMatrix is used for rendering or not.
31 | * False by default, which means that transformMatrix isn't used for rendering
32 | */
33 | public var matrixExposed:Bool = false;
34 |
35 | /**
36 | * Internal helper matrix object. Used for rendering calculations when matrixExposed is set to false
37 | */
38 | var _skewMatrix:Matrix = new Matrix();
39 |
40 | /**
41 | * WARNING: This will remove this sprite entirely. Use kill() if you
42 | * want to disable it temporarily only and reset() it later to revive it.
43 | * Used to clean up memory.
44 | */
45 | override public function destroy():Void
46 | {
47 | skew = FlxDestroyUtil.put(skew);
48 | _skewMatrix = null;
49 | transformMatrix = null;
50 |
51 | super.destroy();
52 | }
53 |
54 | override function drawComplex(camera:FlxCamera):Void
55 | {
56 | _frame.prepareMatrix(_matrix, FlxFrameAngle.ANGLE_0, checkFlipX(), checkFlipY());
57 | _matrix.translate(-origin.x, -origin.y);
58 | _matrix.scale(scale.x, scale.y);
59 |
60 | if (matrixExposed)
61 | {
62 | _matrix.concat(transformMatrix);
63 | }
64 | else
65 | {
66 | if (bakedRotationAngle <= 0)
67 | {
68 | updateTrig();
69 |
70 | if (angle != 0)
71 | _matrix.rotateWithTrig(_cosAngle, _sinAngle);
72 | }
73 |
74 | updateSkewMatrix();
75 | _matrix.concat(_skewMatrix);
76 | }
77 |
78 | getScreenPosition(_point, camera).subtractPoint(offset);
79 | _point.addPoint(origin);
80 | if (isPixelPerfectRender(camera))
81 | _point.floor();
82 |
83 | _matrix.translate(_point.x, _point.y);
84 | camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader);
85 | }
86 |
87 | function updateSkewMatrix():Void
88 | {
89 | _skewMatrix.identity();
90 |
91 | if (skew.x != 0 || skew.y != 0)
92 | {
93 | _skewMatrix.b = skew.y * FlxAngle.TO_RAD;
94 | _skewMatrix.c = skew.x * FlxAngle.TO_RAD;
95 | }
96 |
97 | }
98 |
99 | override public function isSimpleRender(?camera:FlxCamera):Bool
100 | {
101 | if (FlxG.renderBlit)
102 | {
103 | return super.isSimpleRender(camera) && (skew.x == 0) && (skew.y == 0) && !matrixExposed;
104 | }
105 | else
106 | {
107 | return false;
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/source/flixel/tweens/misc/BezierPathNumTween.hx:
--------------------------------------------------------------------------------
1 | package flixel.tweens.misc;
2 |
3 | import flixel.tweens.FlxTween;
4 |
5 | /**
6 | * Tweens a numeric value. See FlxTween.num()
7 | */
8 | class BezierPathNumTween extends FlxTween
9 | {
10 | /**
11 | * The current value.
12 | */
13 | public var value(default, null):Float;
14 |
15 | // Tween information.
16 | var _tweenFunction:Float->Void;
17 | var _points:Array;
18 |
19 | /**
20 | * Clean up references
21 | */
22 | override public function destroy():Void
23 | {
24 | super.destroy();
25 | _tweenFunction = null;
26 | }
27 |
28 | /**
29 | * Tweens the value from one value to another.
30 | *
31 | * @param fromValue Start value.
32 | * @param toValue End value.
33 | * @param duration Duration of the tween.
34 | * @param tweenFunction Optional tween function. See FlxTween.num()
35 | */
36 | public function tween(points:Array, duration:Float, ?tweenFunction:Float->Void):BezierPathNumTween
37 | {
38 | _tweenFunction = tweenFunction;
39 | _points = points;
40 | value = points[0];
41 | this.duration = duration;
42 | start();
43 | return this;
44 | }
45 |
46 | override function update(elapsed:Float):Void
47 | {
48 | super.update(elapsed);
49 | value = bezierPath(scale,_points);
50 |
51 | if (_tweenFunction != null)
52 | _tweenFunction(value);
53 | }
54 |
55 | function bezierPath(t:Float, points:Array):Float {
56 | var n:Int = points.length - 1;
57 | var curve:Float = 0;
58 |
59 | for (i in 0...points.length) {
60 | var coeff:Float = 1;
61 | for (j in 0...i) {
62 | coeff = coeff * (n - j) / (j + 1);
63 | }
64 |
65 | curve += coeff * Math.pow(1 - t, n - i) * Math.pow(t, i) * points[i];
66 | }
67 |
68 | return curve;
69 | }
70 | }
--------------------------------------------------------------------------------
/source/flixel/tweens/misc/BezierPathTween.hx:
--------------------------------------------------------------------------------
1 | package flixel.tweens.misc;
2 |
3 | import flixel.math.FlxPoint;
4 | import flixel.tweens.FlxTween.FlxTweenManager;
5 | import flixel.tweens.FlxTween.TweenOptions;
6 | import flixel.util.FlxDestroyUtil;
7 |
8 | /**
9 | * A series of points which will determine a path from the
10 | * beginning point to the end point using quadratic curves.
11 | */
12 | class BezierPathTween extends FlxTween
13 | {
14 | // Path information.
15 | var _object:Dynamic;
16 | var _properties:Dynamic>;
17 | var _propertyInfos:Array;
18 | var _distance:Float = 0;
19 |
20 | // Curve information.
21 | var _updateCurve:Bool = true;
22 |
23 | function new(Options:TweenOptions, ?manager:FlxTweenManager)
24 | {
25 | super(Options, manager);
26 | }
27 |
28 | function tween(object:Dynamic, properties:Dynamic>, duration:Float){
29 | #if FLX_DEBUG
30 | if (object == null)
31 | throw "Cannot tween variables of an object that is null.";
32 | else if (properties == null)
33 | throw "Cannot tween null properties.";
34 | #end
35 | _object = object;
36 | _properties = properties;
37 | this.duration = duration;
38 | _propertyInfos = [];
39 | start();
40 | initializeVars();
41 | }
42 |
43 | override public function destroy():Void
44 | {
45 | super.destroy();
46 | }
47 |
48 | /**
49 | * Gets the point on the path.
50 | */
51 |
52 | override public function start():BezierPathTween
53 | {
54 | super.start();
55 | return this;
56 | }
57 |
58 | override function update(elapsed:Float):Void
59 | {
60 | var delay:Float = (executions > 0) ? loopDelay : startDelay;
61 |
62 | // Leave properties alone until delay is over
63 | if (_secondsSinceStart < delay)
64 | super.update(elapsed);
65 | else
66 | {
67 | if (Math.isNaN(_propertyInfos[0].startValue))
68 | setStartValues();
69 |
70 | super.update(elapsed);
71 |
72 | if (active)
73 | for (info in _propertyInfos)
74 | if (info.points.length < 3){
75 | Reflect.setProperty(info.object, info.field, info.startValue + info.range * scale);
76 | }
77 | else
78 | Reflect.setProperty(info.object, info.field, bezierPath(scale,info.points));
79 | }
80 | }
81 |
82 | function initializeVars():Void
83 | {
84 | var fieldPaths:Array;
85 | if (Reflect.isObject(_properties))
86 | fieldPaths = Reflect.fields(_properties);
87 | else
88 | throw "Unsupported properties container - use an object containing key/value pairs.";
89 |
90 | for (fieldPath in fieldPaths)
91 | {
92 | var target = _object;
93 | var path = fieldPath.split(".");
94 | var field = path.pop();
95 | for (component in path)
96 | {
97 | target = Reflect.getProperty(target, component);
98 | if (!Reflect.isObject(target))
99 | throw 'The object does not have the property "$component" in "$fieldPath"';
100 | }
101 | var propFieldValues = Reflect.field(_properties, fieldPath);
102 |
103 | var arr:BezierTweenProperty = {
104 | object: target,
105 | field: field,
106 | startValue: Math.NaN,
107 | points: propFieldValues,
108 | range: propFieldValues[propFieldValues.length-1]
109 | };
110 |
111 | _propertyInfos.push(arr);
112 | }
113 | }
114 |
115 | function setStartValues()
116 | {
117 | for (info in _propertyInfos)
118 | {
119 | if (Reflect.getProperty(info.object, info.field) == null)
120 | throw 'The object does not have the property "${info.field}"';
121 | if (Math.isNaN(info.points[0])){
122 | var value:Dynamic = Reflect.getProperty(info.object, info.field);
123 | if (Math.isNaN(value))
124 | throw 'The property "${info.field}" is not numeric.';
125 |
126 | info.startValue = value;
127 | info.points[0] = value;
128 | info.range = info.points[info.points.length-1] - value;
129 | }
130 | else{
131 | info.startValue = info.points[0];
132 | info.range = info.points[info.points.length-1] - info.points[0];
133 | }
134 | }
135 | }
136 |
137 | function bezierPath(t:Float, points:Array):Float {
138 | var n:Int = points.length - 1;
139 | var curve:Float = 0;
140 |
141 | for (i in 0...points.length) {
142 | var coeff:Float = 1;
143 | for (j in 0...i) {
144 | coeff = coeff * (n - j) / (j + 1);
145 | }
146 |
147 | curve += coeff * Math.pow(1 - t, n - i) * Math.pow(t, i) * points[i];
148 | }
149 |
150 | return curve;
151 | }
152 | }
153 |
154 | private typedef BezierTweenProperty =
155 | {
156 | object:Dynamic,
157 | field:String,
158 | startValue:Float,
159 | points:Array,
160 | range:Float
161 | }
--------------------------------------------------------------------------------
/source/import.hx:
--------------------------------------------------------------------------------
1 | #if LEATHER
2 | import states.PlayState;
3 | import game.Song;
4 | import game.Section.SwagSection;
5 | import game.Note;
6 | import ui.FlxScrollableDropDownMenu;
7 | import game.Conductor;
8 | import utilities.CoolUtil;
9 | import game.StrumNote;
10 | import utilities.NoteVariables;
11 | import states.LoadingState;
12 | import states.MusicBeatState;
13 | import substates.MusicBeatSubstate;
14 | #elseif (PSYCH && PSYCHVERSION >= "0.7")
15 | import flixel.addons.ui.FlxUIDropDownMenu;
16 | import backend.Section.SwagSection;
17 | import states.PlayState;
18 | import backend.CoolUtil;
19 | import backend.Conductor;
20 | import backend.ClientPrefs;
21 | import backend.Paths;
22 | import states.LoadingState;
23 | import backend.Difficulty;
24 | #if SCEModchartingTools
25 | import substates.MusicBeatSubstate;
26 | #else
27 | import backend.MusicBeatSubstate;
28 | #end
29 | import objects.Note;
30 | #if SCEModchartingTools
31 | import objects.StrumArrow;
32 | #else
33 | import objects.StrumNote;
34 | #end
35 | import backend.Song;
36 | #else
37 | import Section.SwagSection;
38 | import Song;
39 | import MusicBeatSubstate;
40 | #end
41 |
42 | #if (PSYCH && PSYCHVERSION >= "0.7")
43 | #if LUA_ALLOWED
44 | import psychlua.FunkinLua;
45 | import psychlua.HScript as FunkinHScript;
46 | #end
47 | #end
48 |
49 | #if sys
50 | import sys.FileSystem;
51 | import sys.io.File;
52 | #end
53 |
--------------------------------------------------------------------------------
/source/managers/TweenManager.hx:
--------------------------------------------------------------------------------
1 | package managers;
2 |
3 | import flixel.util.FlxColor;
4 | import flixel.FlxSprite;
5 | import flixel.math.FlxPoint;
6 | import flixel.FlxObject;
7 | import flixel.tweens.FlxTween;
8 | import flixel.tweens.misc.*;
9 |
10 | class TweenManager extends FlxTweenManager
11 | {
12 | public function bezierPathTween(Object:Dynamic, Values:Dynamic>, Duration:Float = 1, ?Options:TweenOptions):BezierPathTween{
13 | @:privateAccess{
14 | var tween = new BezierPathTween(Options, this);
15 | tween.tween(Object, Values, Duration);
16 | return add(tween);
17 | }
18 | }
19 | public function bezierPathNumTween(Points:Array, Duration:Float = 1, ?Options:TweenOptions,?TweenFunction:Float->Void):BezierPathNumTween{
20 | @:privateAccess{
21 | var tween = new BezierPathNumTween(Options, this);
22 | tween.tween(Points, Duration, TweenFunction);
23 | return add(tween);
24 | }
25 | }
26 | /**
27 | * Tweens numeric public properties of an Object. Shorthand for creating a VarTween, starting it and adding it to the TweenManager.
28 | *
29 | * ```haxe
30 | * this.createTween(Object, { x: 500, y: 350, "scale.x": 2 }, 2.0, { ease: easeFunction, onStart: onStart, onUpdate: onUpdate, onComplete: onComplete, type: ONESHOT });
31 | * ```
32 | *
33 | * @param Object The object containing the properties to tween.
34 | * @param Values An object containing key/value pairs of properties and target values.
35 | * @param Duration Duration of the tween in seconds.
36 | * @param Options A structure with tween options.
37 | * @return The added VarTween object.
38 | * @since 4.2.0
39 | */
40 | public function createTween(Object:Dynamic, Values:Dynamic, Duration:Float = 1, ?Options:TweenOptions):FlxTween
41 | {
42 | var daTween = this.tween(Object, Values, Duration, Options);
43 | daTween.manager = this;
44 | return daTween;
45 | }
46 |
47 | /**
48 | * Tweens some numeric value. Shorthand for creating a NumTween, starting it and adding it to the TweenManager. Using it in
49 | * conjunction with a TweenFunction requires more setup, but is faster than VarTween because it doesn't use Reflection.
50 | *
51 | * ```haxe
52 | * function tweenFunction(s:FlxSprite, v:Float) { s.alpha = v; }
53 | * this.createNum(1, 0, 2.0, { ease: easeFunction, onStart: onStart, onUpdate: onUpdate, onComplete: onComplete, type: ONESHOT }, tweenFunction.bind(mySprite));
54 | * ```
55 | *
56 | * Trivia: For historical reasons, you can use either onUpdate or TweenFunction to accomplish the same thing, but TweenFunction
57 | * gives you the updated Float as a direct argument.
58 | *
59 | * @param FromValue Start value.
60 | * @param ToValue End value.
61 | * @param Duration Duration of the tween.
62 | * @param Options A structure with tween options.
63 | * @param TweenFunction A function to be called when the tweened value updates. It is recommended not to use an anonymous
64 | * function if you are maximizing performance, as those will be compiled to Dynamics on cpp.
65 | * @return The added NumTween object.
66 | * @since 4.2.0
67 | */
68 | public function createNum(FromValue:Float, ToValue:Float, Duration:Float = 1, ?Options:TweenOptions, ?TweenFunction:Float->Void):FlxTween
69 | {
70 | var daTween = this.num(FromValue, ToValue, Duration, Options, TweenFunction);
71 | daTween.manager = this;
72 | return daTween;
73 | }
74 |
75 | /**
76 | * Tweens numeric value which represents angle. Shorthand for creating a AngleTween object, starting it and adding it to the TweenManager.
77 | *
78 | * ```haxe
79 | * this.createAngle(Sprite, -90, 90, 2.0, { ease: easeFunction, onStart: onStart, onUpdate: onUpdate, onComplete: onComplete, type: ONESHOT });
80 | * ```
81 | *
82 | * @param Sprite Optional Sprite whose angle should be tweened.
83 | * @param FromAngle Start angle.
84 | * @param ToAngle End angle.
85 | * @param Duration Duration of the tween.
86 | * @param Options A structure with tween options.
87 | * @return The added AngleTween object.
88 | * @since 4.2.0
89 | */
90 | public function createAngle(?Sprite:FlxSprite, FromAngle:Float, ToAngle:Float, Duration:Float = 1, ?Options:TweenOptions):FlxTween
91 | {
92 | var daTween = this.angle(Sprite, FromAngle, ToAngle, Duration, Options);
93 | daTween.manager = this;
94 | return daTween;
95 | }
96 |
97 | /**
98 | * Tweens numeric value which represents color. Shorthand for creating a ColorTween object, starting it and adding it to a TweenPlugin.
99 | *
100 | * ```haxe
101 | * this.createColor(Sprite, 2.0, 0x000000, 0xffffff, 0.0, 1.0, { ease: easeFunction, onStart: onStart, onUpdate: onUpdate, onComplete: onComplete, type: ONESHOT });
102 | * ```
103 | *
104 | * @param Sprite Optional Sprite whose color should be tweened.
105 | * @param Duration Duration of the tween in seconds.
106 | * @param FromColor Start color.
107 | * @param ToColor End color.
108 | * @param Options A structure with tween options.
109 | * @return The added ColorTween object.
110 | * @since 4.2.0
111 | */
112 | public function createColor(?Sprite:FlxSprite, Duration:Float = 1, FromColor:FlxColor, ToColor:FlxColor, ?Options:TweenOptions):FlxTween
113 | {
114 | var daTween = this.color(Sprite, Duration, FromColor, ToColor, Options);
115 | daTween.manager = this;
116 | return daTween;
117 | }
118 |
119 | /**
120 | * Create a new LinearMotion tween.
121 | *
122 | * ```haxe
123 | * this.createLinearMotion(Object, 0, 0, 500, 20, 5, false, { ease: easeFunction, onStart: onStart, onUpdate: onUpdate, onComplete: onComplete, type: ONESHOT });
124 | * ```
125 | *
126 | * @param Object The object to move (FlxObject or FlxSpriteGroup)
127 | * @param FromX X start.
128 | * @param FromY Y start.
129 | * @param ToX X finish.
130 | * @param ToY Y finish.
131 | * @param DurationOrSpeed Duration (in seconds) or speed of the movement.
132 | * @param UseDuration Whether to use the previous param as duration or speed.
133 | * @param Options A structure with tween options.
134 | * @return The LinearMotion object.
135 | * @since 4.2.0
136 | */
137 | public function createLinearMotion(Object:FlxObject, FromX:Float, FromY:Float, ToX:Float, ToY:Float, DurationOrSpeed:Float = 1, UseDuration:Bool = true,
138 | ?Options:TweenOptions):FlxTween
139 | {
140 | var daTween = this.linearMotion(Object, FromX, FromY, ToX, ToY, Options);
141 | daTween.manager = this;
142 | return daTween;
143 | }
144 |
145 | /**
146 | * Create a new QuadMotion tween.
147 | *
148 | * ```haxe
149 | * this.createQuadMotion(Object, 0, 100, 300, 500, 100, 2, 5, false, { ease: easeFunction, onStart: onStart, onUpdate: onUpdate, onComplete: onComplete, type: ONESHOT });
150 | * ```
151 | *
152 | * @param Object The object to move (FlxObject or FlxSpriteGroup)
153 | * @param FromX X start.
154 | * @param FromY Y start.
155 | * @param ControlX X control, used to determine the curve.
156 | * @param ControlY Y control, used to determine the curve.
157 | * @param ToX X finish.
158 | * @param ToY Y finish.
159 | * @param DurationOrSpeed Duration (in seconds) or speed of the movement.
160 | * @param UseDuration Whether to use the previous param as duration or speed.
161 | * @param Options A structure with tween options.
162 | * @return The QuadMotion object.
163 | * @since 4.2.0
164 | */
165 | public function createQuadMotion(Object:FlxObject, FromX:Float, FromY:Float, ControlX:Float, ControlY:Float, ToX:Float, ToY:Float,
166 | DurationOrSpeed:Float = 1, UseDuration:Bool = true, ?Options:TweenOptions):FlxTween
167 | {
168 | var daTween = this.quadMotion(Object, FromX, FromY, ControlX, ControlY, ToX, ToY, DurationOrSpeed, UseDuration, Options);
169 | daTween.manager = this;
170 | return daTween;
171 | }
172 |
173 | /**
174 | * Create a new CubicMotion tween.
175 | *
176 | * ```haxe
177 | * this.createCubicMotion(_sprite, 0, 0, 500, 100, 400, 200, 100, 100, 2, { ease: easeFunction, onStart: onStart, onUpdate: onUpdate, onComplete: onComplete, type: ONESHOT });
178 | * ```
179 | *
180 | * @param Object The object to move (FlxObject or FlxSpriteGroup)
181 | * @param FromX X start.
182 | * @param FromY Y start.
183 | * @param aX First control x.
184 | * @param aY First control y.
185 | * @param bX Second control x.
186 | * @param bY Second control y.
187 | * @param ToX X finish.
188 | * @param ToY Y finish.
189 | * @param Duration Duration of the movement in seconds.
190 | * @param Options A structure with tween options.
191 | * @return The CubicMotion object.
192 | * @since 4.2.0
193 | */
194 | public function createCubicMotion(Object:FlxObject, FromX:Float, FromY:Float, aX:Float, aY:Float, bX:Float, bY:Float, ToX:Float, ToY:Float,
195 | Duration:Float = 1, ?Options:TweenOptions):FlxTween
196 | {
197 | var daTween = this.cubicMotion(Object, FromX, FromY, aX, aY, bX, bY, ToX, ToY, Duration, Options);
198 | daTween.manager = this;
199 | return daTween;
200 | }
201 |
202 | /**
203 | * Create a new CircularMotion tween.
204 | *
205 | * ```haxe
206 | * this.createCircularMotion(Object, 250, 250, 50, 0, true, 2, true, { ease: easeFunction, onStart: onStart, onUpdate: onUpdate, onComplete: onComplete, type: ONESHOT });
207 | * ```
208 | *
209 | * @param Object The object to move (FlxObject or FlxSpriteGroup)
210 | * @param CenterX X position of the circle's center.
211 | * @param CenterY Y position of the circle's center.
212 | * @param Radius Radius of the circle.
213 | * @param Angle Starting position on the circle.
214 | * @param Clockwise If the motion is clockwise.
215 | * @param DurationOrSpeed Duration of the movement in seconds.
216 | * @param UseDuration Duration of the movement.
217 | * @param Ease Optional easer function.
218 | * @param Options A structure with tween options.
219 | * @return The CircularMotion object.
220 | * @since 4.2.0
221 | */
222 | public function createCircularMotion(Object:FlxObject, CenterX:Float, CenterY:Float, Radius:Float, Angle:Float, Clockwise:Bool, DurationOrSpeed:Float = 1,
223 | UseDuration:Bool = true, ?Options:TweenOptions):FlxTween
224 | {
225 | var daTween = this.circularMotion(Object, CenterX, CenterY, Radius, Angle, Clockwise, DurationOrSpeed, UseDuration, Options);
226 | daTween.manager = this;
227 | return daTween;
228 | }
229 |
230 | /**
231 | * Create a new LinearPath tween.
232 | *
233 | * ```haxe
234 | * this.createLinearPath(Object, [FlxPoint.get(0, 0), FlxPoint.get(100, 100)], 2, true, { ease: easeFunction, onStart: onStart, onUpdate: onUpdate, onComplete: onComplete, type: ONESHOT });
235 | * ```
236 | *
237 | * @param Object The object to move (FlxObject or FlxSpriteGroup)
238 | * @param Points An array of at least 2 FlxPoints defining the path
239 | * @param DurationOrSpeed Duration (in seconds) or speed of the movement.
240 | * @param UseDuration Whether to use the previous param as duration or speed.
241 | * @param Options A structure with tween options.
242 | * @return The LinearPath object.
243 | * @since 4.2.0
244 | */
245 | public function createLinearPath(Object:FlxObject, Points:Array, DurationOrSpeed:Float = 1, UseDuration:Bool = true,
246 | ?Options:TweenOptions):FlxTween
247 | {
248 | var daTween = this.linearPath(Object, Points, DurationOrSpeed, UseDuration, Options);
249 | daTween.manager = this;
250 | return daTween;
251 | }
252 |
253 | /**
254 | * Create a new QuadPath tween.
255 | *
256 | * ```haxe
257 | * this.createQuadPath(Object, [FlxPoint.get(0, 0), FlxPoint.get(200, 200), FlxPoint.get(400, 0)], 2, true, { ease: easeFunction, onStart: onStart, onUpdate: onUpdate, onComplete: onComplete, type: ONESHOT });
258 | * ```
259 | *
260 | * @param Object The object to move (FlxObject or FlxSpriteGroup)
261 | * @param Points An array of at least 3 FlxPoints defining the path
262 | * @param DurationOrSpeed Duration (in seconds) or speed of the movement.
263 | * @param UseDuration Whether to use the previous param as duration or speed.
264 | * @param Options A structure with tween options.
265 | * @return The QuadPath object.
266 | * @since 4.2.0
267 | */
268 | public function createQuadPath(Object:FlxObject, Points:Array, DurationOrSpeed:Float = 1, UseDuration:Bool = true,
269 | ?Options:TweenOptions):FlxTween
270 | {
271 | var daTween = this.quadPath(Object, Points, DurationOrSpeed, UseDuration, Options);
272 | daTween.manager = this;
273 | return daTween;
274 | }
275 |
276 | /**
277 | * Tweens value by using bezier path. Minimum 2 points.
278 | *
279 | * ```haxe
280 | * this.createBezierPathTween(Object, { x: [500,1000,500], y: [350,400,400,350]}, 2.0, { ease: easeFunction, onStart: onStart, onUpdate: onUpdate, onComplete: onComplete, type: ONESHOT });
281 | * ```
282 | *
283 | * @param Object The object containing the properties to tween.
284 | * @param Values An object containing key/value pairs of properties and the value as in array containing points. Tip: Use Math.Nan at the first point to use the object's original value!
285 | * @param Duration Duration of the tween in seconds.
286 | * @param Options A structure with tween options.
287 | * @return The added BezierPathTween object.
288 | */
289 | public function createBezierPathTween(Object:Dynamic, Values:Dynamic>, Duration:Float = 1, ?Options:TweenOptions):BezierPathTween
290 | {
291 | var daTween = this.bezierPathTween(Object, Values, Duration, Options);
292 | daTween.manager = this;
293 | return daTween;
294 | }
295 |
296 |
297 | /**
298 | * Cancels all related tweens on the specified object.
299 | *
300 | * Note: Any tweens with the specified fields are cancelled, if the tween has other properties they
301 | * will also be cancelled.
302 | *
303 | * @param Object The object with tweens to cancel.
304 | * @param FieldPaths Optional list of the tween field paths to search for. If null or empty, all tweens on the specified
305 | * object are canceled. Allows dot paths to check child properties.
306 | *
307 | * @since 4.9.0
308 | */
309 | public function cancelTweensByObject(Object:Dynamic, ?FieldPaths:Array):Void
310 | {
311 | this.cancelTweensOf(Object, FieldPaths);
312 | }
313 |
314 | /**
315 | * Immediately updates all tweens on the specified object with the specified fields that
316 | * are not looping (type `FlxTween.LOOPING` or `FlxTween.PINGPONG`) and `active` through
317 | * their endings, triggering their `onComplete` callbacks.
318 | *
319 | * Note: if they haven't yet begun, this will first trigger their `onStart` callback.
320 | *
321 | * Note: their `onComplete` callbacks are triggered in the next frame.
322 | * To trigger them immediately, call `FlxTween.globalManager.update(0);` after this function.
323 | *
324 | * In no case should it trigger an `onUpdate` callback.
325 | *
326 | * Note: Any tweens with the specified fields are completed, if the tween has other properties they
327 | * will also be completed.
328 | *
329 | * @param Object The object with tweens to complete.
330 | * @param FieldPaths Optional list of the tween field paths to search for. If null or empty, all tweens on
331 | * the specified object are completed. Allows dot paths to check child properties.
332 | *
333 | * @since 4.9.0
334 | */
335 | public function completeTweensByObject(Object:Dynamic, ?FieldPaths:Array):Void
336 | {
337 | this.completeTweensOf(Object, FieldPaths);
338 | }
339 |
340 | public function pauseTweens():Void
341 | {
342 | if (this == null)
343 | return;
344 | this.active = false;
345 | }
346 |
347 | public function resumeTweens():Void
348 | {
349 | if (this == null)
350 | return;
351 | this.active = true;
352 | }
353 |
354 | public function destroyTweens():Void
355 | {
356 | if (this == null)
357 | return;
358 | this.clear();
359 | }
360 | }
361 |
--------------------------------------------------------------------------------
/source/modcharting/ModTable.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | import flixel.math.FlxMath;
4 | import flixel.tweens.FlxTween;
5 | import modcharting.Modifier;
6 | #if LEATHER
7 | import game.Conductor;
8 | #end
9 |
10 | class ModTable
11 | {
12 | public var modifiers:Map = new Map();
13 | private var instance:ModchartMusicBeatState = null;
14 | private var renderer:PlayfieldRenderer = null;
15 |
16 | //The table is used to precalculate all the playfield and lane checks on each modifier,
17 | //so it should end up with a lot less loops and if checks each frame
18 | //index table by playfield, then lane, and then loop through each modifier
19 | private var table:Array>> = [];
20 |
21 | public function new(instance:ModchartMusicBeatState, renderer:PlayfieldRenderer)
22 | {
23 | this.instance = instance;
24 | this.renderer = renderer;
25 | loadDefaultModifiers();
26 | reconstructTable();
27 | }
28 |
29 | public function add(mod:Modifier) : Void
30 | {
31 | mod.instance = instance;
32 | mod.renderer = renderer;
33 | remove(mod.tag); //in case you replace one???
34 | modifiers.set(mod.tag, mod);
35 | }
36 | public function remove(tag:String) : Void
37 | {
38 | if (modifiers.exists(tag))
39 | modifiers.remove(tag);
40 | }
41 | public function clear() : Void
42 | {
43 | modifiers.clear();
44 |
45 | loadDefaultModifiers();
46 | }
47 | public function resetMods() : Void
48 | {
49 | for (mod in modifiers)
50 | mod.reset();
51 | }
52 | public function setModTargetLane(tag:String, lane:Int) : Void
53 | {
54 | if (modifiers.exists(tag))
55 | {
56 | modifiers.get(tag).targetLane = lane;
57 | }
58 | }
59 |
60 | public function loadDefaultModifiers() : Void
61 | {
62 | //default modifiers
63 | add(new XModifier('x'));
64 | add(new YModifier('y'));
65 | add(new ZModifier('z'));
66 | add(new ConfusionModifier('confusion'));
67 |
68 | for (i in 0...(NoteMovement.keyCount+NoteMovement.playerKeyCount))
69 | {
70 | add(new XModifier('x'+i, ModifierType.LANESPECIFIC));
71 | add(new YModifier('y'+i, ModifierType.LANESPECIFIC));
72 | add(new ZModifier('z'+i, ModifierType.LANESPECIFIC));
73 | add(new ConfusionModifier('confusion'+i, ModifierType.LANESPECIFIC));
74 | setModTargetLane('x'+i, i);
75 | setModTargetLane('y'+i, i);
76 | setModTargetLane('z'+i, i);
77 | setModTargetLane('confusion'+i, i);
78 | }
79 | }
80 |
81 | public function reconstructTable() : Void
82 | {
83 | table = [];
84 |
85 | for (pf in 0...renderer.playfields.length)
86 | {
87 | if (table[pf] == null)
88 | table[pf] = [];
89 |
90 | for (lane in 0...NoteMovement.totalKeyCount)
91 | {
92 | table[pf].push([]);
93 |
94 | for (mod in modifiers)
95 | {
96 | if (mod.checkLane(lane) && mod.checkPlayField(pf))
97 | {
98 | table[pf][lane].push(mod); //add mod to table
99 | }
100 | }
101 | }
102 | }
103 | }
104 |
105 | public function applyStrumMods(noteData:NotePositionData, lane:Int, pf:Int) : Void
106 | {
107 | if (table[pf] != null && table[pf][lane] != null)
108 | {
109 | var modList:Array = table[pf][lane];
110 | for (mod in modList)
111 | mod.getStrumPath(noteData, lane, pf);
112 | }
113 | }
114 | public function applyNoteMods(noteData:NotePositionData, lane:Int, curPos:Float, pf:Int) : Void
115 | {
116 | if (table[pf] != null && table[pf][lane] != null)
117 | {
118 | var modList:Array = table[pf][lane];
119 | for (mod in modList)
120 | mod.getNotePath(noteData, lane, curPos, pf);
121 | }
122 | }
123 | public function applyNoteDistMods(noteDist:Float, lane:Int, pf:Int) : Float
124 | {
125 | if (table[pf] != null && table[pf][lane] != null)
126 | {
127 | var modList:Array = table[pf][lane];
128 | for (mod in modList)
129 | noteDist = mod.getNoteDist(noteDist, lane, 0, pf);
130 | }
131 | return noteDist;
132 | }
133 | public function applyCurPosMods(lane:Int, curPos:Float, pf:Int) : Float
134 | {
135 | if (table[pf] != null && table[pf][lane] != null)
136 | {
137 | var modList:Array = table[pf][lane];
138 | for (mod in modList)
139 | curPos = mod.getNoteCurPos(lane, curPos, pf);
140 | }
141 | return curPos;
142 | }
143 | public function applyIncomingAngleMods(lane:Int, curPos:Float, pf:Int) : Array
144 | {
145 | var incomingAngle:Array = [0,0];
146 | if (table[pf] != null && table[pf][lane] != null)
147 | {
148 | var modList:Array = table[pf][lane];
149 | for (mod in modList)
150 | {
151 | var ang = mod.getIncomingAngle(lane, curPos, pf); //need to get incoming angle before
152 | incomingAngle[0] += ang[0];
153 | incomingAngle[1] += ang[1];
154 | }
155 | }
156 | return incomingAngle;
157 | }
158 |
159 |
160 |
161 | public function tweenModifier(modifier:String, val:Float, time:Float, ease:String, beat:Float, ?tag:String = null)
162 | {
163 | var modifiers:Map = renderer.modifierTable.modifiers;
164 | if (modifiers.exists(modifier))
165 | {
166 | var easefunc = ModchartUtil.getFlxEaseByString(ease);
167 | if (Conductor.songPosition >= ModchartUtil.getTimeFromBeat(beat)+(time*1000)) //cancel if should have ended
168 | {
169 | modifiers.get(modifier).currentValue = val;
170 | return;
171 | }
172 | time /= renderer.speed;
173 | var tween = renderer.createTween(modifiers.get(modifier), {currentValue: val}, time, {ease: easefunc,
174 | onComplete: function(twn:FlxTween) {
175 | var modifierTag:String = (tag != null ? tag : modifier);
176 | #if PSYCH
177 | #if (PSYCHVERSION >= "0.7")
178 | PlayState.instance.callOnScripts("onModifierComplete", [modifierTag]);
179 | #else
180 | PlayState.instance.callOnLuas("onModifierComplete", [modifierTag]);
181 | #end
182 | #end
183 | }
184 | });
185 | if (Conductor.songPosition > ModchartUtil.getTimeFromBeat(beat)) //skip to where it should be i guess??
186 | {
187 | @:privateAccess
188 | tween._secondsSinceStart += ((Conductor.songPosition-ModchartUtil.getTimeFromBeat(beat))*0.001);
189 | @:privateAccess
190 | tween.update(0);
191 | }
192 | if (renderer.editorPaused)
193 | tween.active = false;
194 | }
195 | }
196 |
197 | public function tweenModifierSubValue(modifier:String, subValue:String, val:Float, time:Float, ease:String, beat:Float, ?tag:String = null)
198 | {
199 | var modifiers:Map = renderer.modifierTable.modifiers;
200 | if (modifiers.exists(modifier))
201 | {
202 | if (modifiers.get(modifier).subValues.exists(subValue))
203 | {
204 | var easefunc = ModchartUtil.getFlxEaseByString(ease);
205 | var tag = modifier+' '+subValue;
206 |
207 | var startValue = modifiers.get(modifier).subValues.get(subValue).value;
208 |
209 | if (Conductor.songPosition >= ModchartUtil.getTimeFromBeat(beat)+(time*1000)) //cancel if should have ended
210 | {
211 | modifiers.get(modifier).subValues.get(subValue).value = val;
212 | return;
213 | }
214 | time /= renderer.speed;
215 | var tween = renderer.createTweenNum(startValue, val, time, {ease: easefunc,
216 | onComplete: function(twn:FlxTween) {
217 | if (modifiers.exists(modifier))
218 | modifiers.get(modifier).subValues.get(subValue).value = val;
219 | var modifierTag:String = (tag != null ? tag : '$modifier-$subValue');
220 | #if PSYCH
221 | #if (PSYCHVERSION >= "0.7")
222 | PlayState.instance.callOnScripts("onModifierComplete", [modifier, subValue]);
223 | #else
224 | PlayState.instance.callOnLuas("onModifierComplete", [modifier, subValue]);
225 | #end
226 | #end
227 | },
228 | onUpdate: function(twn:FlxTween) {
229 | //need to update like this because its inside a map
230 | if (modifiers.exists(modifier))
231 | modifiers.get(modifier).subValues.get(subValue).value = FlxMath.lerp(startValue, val, easefunc(twn.percent));
232 | }
233 | });
234 | if (Conductor.songPosition > ModchartUtil.getTimeFromBeat(beat)) //skip to where it should be i guess??
235 | {
236 | @:privateAccess
237 | tween._secondsSinceStart += ((Conductor.songPosition-ModchartUtil.getTimeFromBeat(beat))*0.001);
238 | @:privateAccess
239 | tween.update(0);
240 | }
241 | if (renderer.editorPaused)
242 | tween.active = false;
243 | }
244 |
245 | }
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/source/modcharting/ModchartEvent.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | class ModchartEvent
4 | {
5 | public var time:Float = 0;
6 | public var func:Array->Void;
7 | public var args:Array;
8 | public function new(time:Float, func:Array->Void, args:Array)
9 | {
10 | this.time = time;
11 | this.func = func;
12 | this.args = args;
13 | }
14 | /*public function call()
15 | {
16 | Reflect.callMethod(null, func, args);
17 | }*/
18 | }
--------------------------------------------------------------------------------
/source/modcharting/ModchartEventManager.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | #if LEATHER
4 | import game.Conductor;
5 | #end
6 |
7 | class ModchartEventManager
8 | {
9 | private var renderer:PlayfieldRenderer;
10 | public function new(renderer:PlayfieldRenderer)
11 | {
12 | this.renderer = renderer;
13 | }
14 | private var events:Array = [];
15 | public function update(elapsed:Float)
16 | {
17 | if (events.length > 1)
18 | {
19 | events.sort(function(a, b){
20 | if (a.time < b.time)
21 | return -1;
22 | else if (a.time > b.time)
23 | return 1;
24 | else
25 | return 0;
26 | });
27 | }
28 | while(events.length > 0) {
29 | var event:ModchartEvent = events[0];
30 | if(Conductor.songPosition < event.time) {
31 | break;
32 | }
33 | //Reflect.callMethod(this, event.func, event.args);
34 | event.func(event.args);
35 | events.shift();
36 | }
37 | Modifier.beat = ((Conductor.songPosition *0.001)*(Conductor.bpm/60));
38 | }
39 | public function addEvent(beat:Float, func:Array->Void, args:Array)
40 | {
41 | var time = ModchartUtil.getTimeFromBeat(beat);
42 | events.push(new ModchartEvent(time, func, args));
43 | }
44 | public function clearEvents()
45 | {
46 | events = [];
47 | }
48 | }
--------------------------------------------------------------------------------
/source/modcharting/ModchartFile.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | import flixel.math.FlxMath;
4 | import haxe.Exception;
5 | import haxe.Json;
6 | import haxe.format.JsonParser;
7 | import lime.utils.Assets;
8 | #if LEATHER
9 | import states.PlayState;
10 | import game.Note;
11 | import game.Conductor;
12 | #if polymod
13 | import polymod.backends.PolymodAssets;
14 | #end
15 | #end
16 | #if sys
17 | import sys.FileSystem;
18 | import sys.io.File;
19 | #end
20 | #if hscript
21 | import hscript.*;
22 | #end
23 | #if (HSCRIPT_ALLOWED && PSYCH && PSYCHVERSION >= "0.7")
24 | import psychlua.HScript as FunkinHScript;
25 | #end
26 | using StringTools;
27 |
28 | typedef ModchartJson =
29 | {
30 | var modifiers:Array>;
31 | var events:Array>;
32 | var playfields:Int;
33 | }
34 |
35 | class ModchartFile
36 | {
37 | //used for indexing
38 | public static final MOD_NAME = 0; //the modifier name
39 | public static final MOD_CLASS = 1; //the class/custom mod it uses
40 | public static final MOD_TYPE = 2; //the type, which changes if its for the player, opponent, a specific lane or all
41 | public static final MOD_PF = 3; //the playfield that mod uses
42 | public static final MOD_LANE = 4; //the lane the mod uses
43 |
44 | public static final EVENT_TYPE = 0; //event type (set or ease)
45 | public static final EVENT_DATA = 1; //event data
46 | public static final EVENT_REPEAT = 2; //event repeat data
47 |
48 | public static final EVENT_TIME = 0; //event time (in beats)
49 | public static final EVENT_SETDATA = 1; //event data (for sets)
50 | public static final EVENT_EASETIME = 1; //event ease time
51 | public static final EVENT_EASE = 2; //event ease
52 | public static final EVENT_EASEDATA = 3; //event data (for eases)
53 |
54 | public static final EVENT_REPEATBOOL = 0; //if event should repeat
55 | public static final EVENT_REPEATCOUNT = 1; //how many times it repeats
56 | public static final EVENT_REPEATBEATGAP = 2; //how many beats in between each repeat
57 |
58 |
59 | public var data:ModchartJson = null;
60 | private var renderer:PlayfieldRenderer;
61 | public var scriptListen:Bool = false;
62 | #if hscript
63 | public var customModifiers:Map = new Map();
64 | #end
65 | public var hasDifficultyModchart:Bool = false; //so it loads false as default!
66 |
67 | public function new(renderer:PlayfieldRenderer)
68 | {
69 | #if PSYCH
70 | #if (PSYCHVERSION >= "0.7")
71 | data = loadFromJson(PlayState.SONG.song.toLowerCase(), Difficulty.getString().toLowerCase() == null ? Difficulty.defaultList[PlayState.storyDifficulty] : Difficulty.getString().toLowerCase());
72 | #elseif (PSYCHVERSION < "0.7")
73 | data = loadFromJson(PlayState.SONG.song.toLowerCase(), CoolUtil.difficultyString().toLowerCase() == null ? CoolUtil.difficulties[PlayState.storyDifficulty] : CoolUtil.difficultyString().toLowerCase());
74 | #end
75 | #else
76 | data = loadFromJson(PlayState.SONG.song.toLowerCase(), PlayState.storyDifficultyStr);
77 | #end
78 | this.renderer = renderer;
79 | renderer.modchart = this;
80 | loadPlayfields();
81 | loadModifiers();
82 | loadEvents();
83 | }
84 |
85 | public function loadFromJson(folder:String, difficulty:String):ModchartJson //load da shit
86 | {
87 | var rawJson = null;
88 | var filePath = null;
89 |
90 | var folderShit:String = "";
91 |
92 | var moddyFile:String = Paths.json(#if PSYCH Paths.formatToSongPath(folder) #else PlayState.SONG.song #end + '/modchart-' + difficulty.toLowerCase());
93 | var moddyFile2:String = Paths.json(#if PSYCH Paths.formatToSongPath(folder) #else PlayState.SONG.song #end + '/modchart');
94 |
95 | #if MODS_ALLOWED
96 | var moddyFileMods:String = Paths.modsJson(#if PSYCH Paths.formatToSongPath(folder) #else PlayState.SONG.song #end + '/modchart-' + difficulty.toLowerCase());
97 | var moddyFileMods2:String = Paths.modsJson(#if PSYCH Paths.formatToSongPath(folder) #else PlayState.SONG.song #end + '/modchart');
98 | #end
99 |
100 | #if PSYCH
101 | try
102 | {
103 |
104 | #if sys
105 | #if MODS_ALLOWED
106 | if(FileSystem.exists(moddyFileMods) && difficulty.toLowerCase() != null)
107 | hasDifficultyModchart = true;
108 | if (FileSystem.exists(moddyFileMods2) && !FileSystem.exists(moddyFileMods))
109 | hasDifficultyModchart = false;
110 | else if(FileSystem.exists(moddyFileMods2) && difficulty.toLowerCase() == null && !FileSystem.exists(moddyFileMods)) hasDifficultyModchart = false;
111 | #end
112 |
113 | if(FileSystem.exists(moddyFile) && difficulty.toLowerCase() != null)
114 | hasDifficultyModchart = true;
115 | if (FileSystem.exists(moddyFile) && !FileSystem.exists(moddyFile))
116 | hasDifficultyModchart = false;
117 | else if(FileSystem.exists(moddyFile2) && difficulty.toLowerCase() == null && !FileSystem.exists(moddyFile)) hasDifficultyModchart = false;
118 |
119 | #if MODS_ALLOWED
120 | if (hasDifficultyModchart)
121 | {
122 | rawJson = File.getContent(moddyFileMods).trim();
123 | folderShit = moddyFileMods.replace('modchart-' + difficulty.toLowerCase() + '.json', "customMods/");
124 |
125 | trace('${difficulty} Modchart Found In Mods! loading modchart-${difficulty.toLowerCase()}.json');
126 | }
127 | else
128 | {
129 | rawJson = File.getContent(moddyFileMods2).trim();
130 | folderShit = moddyFileMods2.replace('modchart.json', "customMods/");
131 |
132 | trace('${difficulty} Modchart Has Not Been Found In Mods! loading modchart.json');
133 | }
134 | #end
135 |
136 | if (hasDifficultyModchart)
137 | {
138 | rawJson = File.getContent(moddyFile).trim();
139 | folderShit = moddyFile.replace('modchart-' + difficulty.toLowerCase() + '.json', "customMods/");
140 |
141 | trace('${difficulty} Modchart Found! loading modchart-${difficulty.toLowerCase()}.json');
142 | }
143 | else
144 | {
145 | rawJson = File.getContent(moddyFile2).trim();
146 | folderShit = moddyFile2.replace('modchart.json', "customMods/");
147 |
148 | trace('${difficulty} Modchart Has Not Been Found! loading modchart.json');
149 | }
150 | #else
151 | #if MODS_ALLOWED
152 | if(Assets.exists(moddyFileMods) && difficulty.toLowerCase() != null)
153 | hasDifficultyModchart = true;
154 | if (Assets.exists(moddyFileMods2) && !Assets.exists(moddyFileMods))
155 | hasDifficultyModchart = false;
156 | else if(Assets.exists(moddyFileMods2) && difficulty.toLowerCase() == null && !Assets.exists(moddyFileMods)) hasDifficultyModchart = false;
157 | #end
158 |
159 | if(Assets.exists(moddyFile) && difficulty.toLowerCase() != null)
160 | hasDifficultyModchart = true;
161 | if (Assets.exists(moddyFile) && !Assets.exists(moddyFile))
162 | hasDifficultyModchart = false;
163 | else if(Assets.exists(moddyFile2) && difficulty.toLowerCase() == null && !Assets.exists(moddyFile)) hasDifficultyModchart = false;
164 |
165 | #if MODS_ALLOWED
166 | if (hasDifficultyModchart)
167 | {
168 | rawJson = File.getContent(moddyFileMods).trim();
169 | folderShit = moddyFileMods.replace('modchart-' + difficulty.toLowerCase() + '.json', "customMods/");
170 |
171 | trace('${difficulty} Modchart Found In Mods! loading modchart-${difficulty.toLowerCase()}.json');
172 | }
173 | else
174 | {
175 | rawJson = File.getContent(moddyFileMods2).trim();
176 | folderShit = moddyFileMods2.replace('modchart.json', "customMods/");
177 |
178 | trace('${difficulty} Modchart Has Not Been Found In Mods! loading modchart.json');
179 | }
180 | #end
181 |
182 | if (hasDifficultyModchart)
183 | {
184 | rawJson = File.getContent(moddyFile).trim();
185 | folderShit = moddyFile.replace('modchart-' + difficulty.toLowerCase() + '.json', "customMods/");
186 |
187 | trace('${difficulty} Modchart Found! loading modchart-${difficulty.toLowerCase()}.json');
188 | }
189 | else
190 | {
191 | rawJson = File.getContent(moddyFile2).trim();
192 | folderShit = moddyFile2.replace('modchart.json', "customMods/");
193 |
194 | trace('${difficulty} Modchart Has Not Been Found! loading modchart.json');
195 | }
196 | #end
197 | }
198 | catch(e:Dynamic)
199 | {
200 | trace(e);
201 | }
202 | #end
203 |
204 | if (rawJson == null)
205 | {
206 | try
207 | {
208 | #if MODS_ALLOWED
209 | if (hasDifficultyModchart)
210 | {
211 |
212 | #if LEATHER
213 | filePath = Paths.json("song data/" + folder + '/modchart-' + difficulty.toLowerCase());
214 | folderShit = PolymodAssets.getPath(filePath.replace('modchart-' + difficulty.toLowerCase() + '.json', "customMods/"));
215 | #else
216 | filePath = Paths.modsJson(folder + '/modchart-' + difficulty.toLowerCase());
217 | folderShit = filePath.replace('modchart-' + difficulty.toLowerCase() + '.json', "customMods/");
218 | #end
219 |
220 | trace('${difficulty} Modchart FolderShit Found In Mods! loading modchart-${difficulty.toLowerCase()}.json');
221 | }
222 | else
223 | {
224 | #if LEATHER
225 | filePath = Paths.json("song data/" + folder + '/modchart');
226 | folderShit = PolymodAssets.getPath(filePath.replace('modchart.json', "customMods/"));
227 | #else
228 | filePath = Paths.modsJson(folder + '/modchart');
229 | folderShit = filePath.replace('modchart.json', "customMods/");
230 | #end
231 |
232 | trace('${difficulty} Modchart Has No FolderShit Found In Mods! loading modchart.json');
233 | }
234 | #end
235 |
236 |
237 | if (hasDifficultyModchart)
238 | {
239 | #if LEATHER
240 | filePath = Paths.json("song data/" + folder + '/modchart-' + difficulty.toLowerCase());
241 | folderShit = PolymodAssets.getPath(filePath.replace('modchart-' + difficulty.toLowerCase() + '.json', "customMods/"));
242 | #else
243 | filePath = Paths.json(folder + '/modchart-' + difficulty.toLowerCase());
244 | folderShit = filePath.replace('modchart-' + difficulty.toLowerCase() + '.json', "customMods/");
245 | #end
246 |
247 | trace('${difficulty} Modchart FolderShit Found! loading modchart-${difficulty.toLowerCase()}.json');
248 | }
249 | else
250 | {
251 | #if LEATHER
252 | filePath = Paths.json("song data/" + folder + '/modchart');
253 | folderShit = PolymodAssets.getPath(filePath.replace('modchart.json', "customMods/"));
254 | #else
255 | filePath = Paths.json(folder + '/modchart');
256 | folderShit = filePath.replace('modchart.json', "customMods/");
257 | #end
258 |
259 | trace('${difficulty} Modchart Has No FolderShit Found! loading modchart.json');
260 | }
261 | }
262 | catch(e:Dynamic)
263 | {
264 | trace(e);
265 | }
266 |
267 | trace(filePath);
268 | #if sys
269 | if(FileSystem.exists(filePath))
270 | rawJson = File.getContent(filePath).trim();
271 | else #end //should become else if i think???
272 | if (Assets.exists(filePath))
273 | rawJson = Assets.getText(filePath).trim();
274 |
275 | }
276 | var json:ModchartJson = null;
277 | if (rawJson != null)
278 | {
279 | for (i in 0...difficulty.length)
280 | json = cast Json.parse(rawJson);
281 | trace('loaded json');
282 | trace(folderShit);
283 |
284 | #if (hscript && sys)
285 | if (FileSystem.isDirectory(folderShit))
286 | {
287 | trace("folder le exists");
288 | for (file in FileSystem.readDirectory(folderShit))
289 | {
290 | trace(file);
291 | if(file.endsWith('.hx')) //custom mods!!!!
292 | {
293 | var scriptStr = File.getContent(folderShit + file);
294 | var scriptInit:Dynamic = null;
295 | scriptInit = #if (HSCRIPT_ALLOWED && PSYCH && PSYCHVERSION >= "0.7") new FunkinHScript(null, scriptStr) #else new CustomModifierScript(scriptStr) #end;
296 | customModifiers.set(file.replace(".hx", ""), scriptInit);
297 | trace('loaded custom mod: ' + file);
298 | }
299 | }
300 | }
301 | #end
302 | }
303 | else
304 | {
305 | json = {modifiers: [], events: [], playfields: 1};
306 | }
307 | return json;
308 | }
309 | public function loadEmpty()
310 | {
311 | data.modifiers = [];
312 | data.events = [];
313 | data.playfields = 1;
314 | }
315 |
316 | public function loadModifiers()
317 | {
318 | if (data == null || renderer == null)
319 | return;
320 | renderer.modifierTable.clear();
321 | for (i in data.modifiers)
322 | {
323 | ModchartFuncs.startMod(i[MOD_NAME], i[MOD_CLASS], i[MOD_TYPE], Std.parseInt(i[MOD_PF]), renderer.instance);
324 | if (i[MOD_LANE] != null)
325 | ModchartFuncs.setModTargetLane(i[MOD_NAME], i[MOD_LANE], renderer.instance);
326 | }
327 | renderer.modifierTable.reconstructTable();
328 | }
329 | public function loadPlayfields()
330 | {
331 | if (data == null || renderer == null)
332 | return;
333 |
334 | renderer.playfields = [];
335 | for (i in 0...data.playfields)
336 | renderer.addNewPlayfield(0,0,0,1);
337 | }
338 | public function loadEvents()
339 | {
340 | if (data == null || renderer == null)
341 | return;
342 | renderer.eventManager.clearEvents();
343 | for (i in data.events)
344 | {
345 | if (i[EVENT_REPEAT] == null) //add repeat data if it doesnt exist
346 | i[EVENT_REPEAT] = [false, 1, 0];
347 |
348 | if (i[EVENT_REPEAT][EVENT_REPEATBOOL])
349 | {
350 | for (j in 0...(Std.int(i[EVENT_REPEAT][EVENT_REPEATCOUNT])+1))
351 | {
352 | addEvent(i, (j*i[EVENT_REPEAT][EVENT_REPEATBEATGAP]));
353 | }
354 | }
355 | else
356 | {
357 | addEvent(i);
358 | }
359 |
360 | }
361 | }
362 | private function addEvent(i:Array, ?beatOffset:Float = 0)
363 | {
364 | switch(i[EVENT_TYPE])
365 | {
366 | case "ease":
367 | ModchartFuncs.ease(Std.parseFloat(i[EVENT_DATA][EVENT_TIME])+beatOffset, Std.parseFloat(i[EVENT_DATA][EVENT_EASETIME]), i[EVENT_DATA][EVENT_EASE], i[EVENT_DATA][EVENT_EASEDATA], renderer.instance);
368 | case "set":
369 | ModchartFuncs.set(Std.parseFloat(i[EVENT_DATA][EVENT_TIME])+beatOffset, i[EVENT_DATA][EVENT_SETDATA], renderer.instance);
370 | case "hscript":
371 | //maybe just run some code???
372 | }
373 | }
374 |
375 | public function createDataFromRenderer() //a way to convert script modcharts into json modcharts
376 | {
377 | if (renderer == null)
378 | return;
379 |
380 | data.playfields = renderer.playfields.length;
381 | scriptListen = true;
382 | }
383 | }
384 |
385 | #if hscript
386 | class CustomModifierScript
387 | {
388 | public var interp:Interp = null;
389 | var script:Expr;
390 | var parser:Parser;
391 | public function new(scriptStr:String)
392 | {
393 | parser = new Parser();
394 | parser.allowTypes = true;
395 | parser.allowMetadata = true;
396 | parser.allowJSON = true;
397 |
398 | try
399 | {
400 | interp = new Interp();
401 | script = parser.parseString(scriptStr); //load da shit
402 | interp.execute(script);
403 | }
404 | catch(e)
405 | {
406 | lime.app.Application.current.window.alert(e.message, 'Error on custom mod .hx!');
407 | return;
408 | }
409 | init();
410 | }
411 | private function init()
412 | {
413 | if (interp == null)
414 | return;
415 |
416 | #if LEATHER
417 | interp.variables.set('mod', Modifier); //the game crashes without this???????? what??????????? -- fue glow
418 | #end
419 |
420 | interp.variables.set('Math', Math);
421 | interp.variables.set('PlayfieldRenderer', PlayfieldRenderer);
422 | interp.variables.set('ModchartUtil', ModchartUtil);
423 | interp.variables.set('Modifier', Modifier);
424 | interp.variables.set('ModifierSubValue', Modifier.ModifierSubValue);
425 | interp.variables.set('BeatXModifier', Modifier.BeatXModifier);
426 | interp.variables.set('NoteMovement', NoteMovement);
427 | interp.variables.set('NotePositionData', NotePositionData);
428 | interp.variables.set('ModchartFile', ModchartFile);
429 | interp.variables.set('FlxG', flixel.FlxG);
430 | interp.variables.set('FlxSprite', flixel.FlxSprite);
431 | interp.variables.set('FlxMath', FlxMath);
432 | interp.variables.set('FlxCamera', flixel.FlxCamera);
433 | interp.variables.set('FlxTimer', flixel.util.FlxTimer);
434 | interp.variables.set('FlxTween', flixel.tweens.FlxTween);
435 | interp.variables.set('FlxEase', flixel.tweens.FlxEase);
436 | interp.variables.set('PlayState', #if (PSYCH && PSYCHVERSION >= "0.7") states.PlayState #else PlayState #end);
437 | interp.variables.set('game', #if (PSYCH && PSYCHVERSION >= "0.7") states.PlayState.instance #else PlayState.instance #end);
438 | interp.variables.set('Paths', #if (PSYCH && PSYCHVERSION >= "0.7") backend.Paths #else Paths #end);
439 | interp.variables.set('Conductor', #if (PSYCH && PSYCHVERSION >= "0.7") backend.Conductor #else Conductor #end);
440 | interp.variables.set('StringTools', StringTools);
441 | interp.variables.set('Note', #if (PSYCH && PSYCHVERSION >= "0.7") objects.Note #else Note #end);
442 |
443 | #if PSYCH
444 | interp.variables.set('ClientPrefs', #if (PSYCHVERSION >= "0.7") backend.ClientPrefs #else ClientPrefs #end);
445 | interp.variables.set('ColorSwap', #if (PSYCHVERSION >= "0.7") shaders.ColorSwap #else ColorSwap #end);
446 | #end
447 |
448 |
449 | }
450 | public function call(event:String, args:Array)
451 | {
452 | if (interp == null)
453 | return;
454 | if (interp.variables.exists(event)) //make sure it exists
455 | {
456 | try
457 | {
458 | if (args.length > 0)
459 | Reflect.callMethod(null, interp.variables.get(event), args);
460 | else
461 | interp.variables.get(event)(); //if function doesnt need an arg
462 | }
463 | catch(e)
464 | {
465 | lime.app.Application.current.window.alert(e.message, 'Error on custom mod .hx!');
466 | }
467 | }
468 | }
469 | public function initMod(mod:Modifier)
470 | {
471 | call("initMod", [mod]);
472 | }
473 |
474 | public function destroy()
475 | {
476 | interp = null;
477 | }
478 | }
479 | #end
480 |
--------------------------------------------------------------------------------
/source/modcharting/ModchartFuncs.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | import haxe.Json;
4 | import openfl.net.FileReference;
5 | import flixel.FlxG;
6 | #if LUA_ALLOWED
7 | import llua.Lua;
8 | import llua.LuaL;
9 | import llua.State;
10 | import llua.Convert;
11 | #end
12 |
13 | #if LEATHER
14 | import states.PlayState;
15 | import game.Conductor;
16 | #if linc_luajit
17 | import modding.ModchartUtilities;
18 | #end
19 | import modding.scripts.languages.HScript;
20 | #end
21 |
22 | #if (PSYCH && PSYCHVERSION >= "0.7")
23 | #if LUA_ALLOWED
24 | import psychlua.FunkinLua;
25 | import psychlua.HScript as FunkinHScript;
26 | #end
27 | #end
28 |
29 | import modcharting.Modifier;
30 | import modcharting.PlayfieldRenderer;
31 | import modcharting.NoteMovement;
32 | import modcharting.ModchartUtil;
33 |
34 | import openfl.events.Event;
35 | import openfl.events.IOErrorEvent;
36 |
37 | using StringTools;
38 |
39 | //for lua and hscript
40 | class ModchartFuncs
41 | {
42 | public static function loadLuaFunctions(#if (PSYCH && PSYCHVERSION >= "0.7") funkin:FunkinLua #end)
43 | {
44 | #if PSYCH
45 | #if LUA_ALLOWED
46 | #if !(PSYCHVERSION >= "0.7")
47 | for (funkin in PlayState.instance.luaArray)
48 | {
49 | #if hscript
50 | funkin.initHaxeModule();
51 | #end
52 | #end
53 | Lua_helper.add_callback(funkin.lua, 'startMod', function(name:String, modClass:String, type:String = '', pf:Int = -1){
54 | startMod(name,modClass,type,pf);
55 |
56 | PlayState.instance.playfieldRenderer.modifierTable.reconstructTable(); //needs to be reconstructed for lua modcharts
57 | });
58 | Lua_helper.add_callback(funkin.lua, 'setMod', function(name:String, value:Float){
59 | setMod(name, value);
60 | });
61 | Lua_helper.add_callback(funkin.lua, 'setSubMod', function(name:String, subValName:String, value:Float){
62 | setSubMod(name, subValName,value);
63 | });
64 | Lua_helper.add_callback(funkin.lua, 'setModTargetLane', function(name:String, value:Int){
65 | setModTargetLane(name, value);
66 | });
67 | Lua_helper.add_callback(funkin.lua, 'setModPlayfield', function(name:String, value:Int){
68 | setModPlayfield(name,value);
69 | });
70 | Lua_helper.add_callback(funkin.lua, 'addPlayfield', function(?x:Float = 0, ?y:Float = 0, ?z:Float = 0){
71 | addPlayfield(x,y,z);
72 | });
73 | Lua_helper.add_callback(funkin.lua, 'removePlayfield', function(idx:Int){
74 | removePlayfield(idx);
75 | });
76 | Lua_helper.add_callback(funkin.lua, 'tweenModifier', function(modifier:String, val:Float, time:Float, ease:String, ?tag:String = null){
77 | tweenModifier(modifier,val,time,ease,null,tag);
78 | });
79 | Lua_helper.add_callback(funkin.lua, 'tweenModifierSubValue', function(modifier:String, subValue:String, val:Float, time:Float, ease:String, ?tag:String = null){
80 | tweenModifierSubValue(modifier,subValue,val,time,ease,null,tag);
81 | });
82 | Lua_helper.add_callback(funkin.lua, 'setModEaseFunc', function(name:String, ease:String){
83 | setModEaseFunc(name,ease);
84 | });
85 | Lua_helper.add_callback(funkin.lua, 'set', function(beat:Float, argsAsString:String){
86 | set(beat, argsAsString);
87 | });
88 | Lua_helper.add_callback(funkin.lua, 'ease', function(beat:Float, time:Float, easeStr:String, argsAsString:String, ?tag:String = null){
89 | ease(beat, time, easeStr, argsAsString, null, tag);
90 | });
91 | #if !(PSYCHVERSION >= "0.7") } #end
92 |
93 | #if (PSYCHVERSION >= "0.7")
94 | loadHaxeFunctions(funkin);
95 | #end
96 | #end
97 | #if !(PSYCHVERSION >= "0.7")
98 | #if hscript
99 | if (FunkinLua.hscript != null)
100 | {
101 | FunkinLua.hscript.variables.set('Math', Math);
102 | FunkinLua.hscript.variables.set('PlayfieldRenderer', PlayfieldRenderer);
103 | FunkinLua.hscript.variables.set('ModchartUtil', ModchartUtil);
104 | FunkinLua.hscript.variables.set('Modifier', Modifier);
105 | FunkinLua.hscript.variables.set('NoteMovement', NoteMovement);
106 | FunkinLua.hscript.variables.set('NotePositionData', NotePositionData);
107 | FunkinLua.hscript.variables.set('ModchartFile', ModchartFile);
108 | }
109 | #end
110 | #end
111 |
112 | #elseif (LEATHER && linc_luajit)
113 | @:privateAccess
114 | {
115 | ModchartUtilities.instance.setLuaFunction('startMod', function(name:String, modClass:String, type:String = '', pf:Int = -1){
116 | startMod(name,modClass,type,pf);
117 |
118 | PlayState.instance.playfieldRenderer.modifierTable.reconstructTable(); //needs to be reconstructed for lua modcharts
119 | });
120 | ModchartUtilities.instance.setLuaFunction('setMod', function(name:String, value:Float){
121 | setMod(name, value);
122 | });
123 | ModchartUtilities.instance.setLuaFunction('setSubMod', function(name:String, subValName:String, value:Float){
124 | setSubMod(name, subValName,value);
125 | });
126 | ModchartUtilities.instance.setLuaFunction('setModTargetLane', function(name:String, value:Int){
127 | setModTargetLane(name, value);
128 | });
129 | ModchartUtilities.instance.setLuaFunction('setModPlayfield', function(name:String, value:Int){
130 | setModPlayfield(name,value);
131 | });
132 | ModchartUtilities.instance.setLuaFunction('addPlayfield', function(?x:Float = 0, ?y:Float = 0, ?z:Float = 0){
133 | addPlayfield(x,y,z);
134 | });
135 | ModchartUtilities.instance.setLuaFunction('removePlayfield', function(idx:Int){
136 | removePlayfield(idx);
137 | });
138 | ModchartUtilities.instance.setLuaFunction('tweenModifier', function(modifier:String, val:Float, time:Float, ease:String, ?tag:String = null){
139 | tweenModifier(modifier,val,time,ease,null,tag);
140 | });
141 | ModchartUtilities.instance.setLuaFunction('tweenModifierSubValue', function(modifier:String, subValue:String, val:Float, time:Float, ease:String, ?tag:String = null){
142 | tweenModifierSubValue(modifier,subValue,val,time,ease,null,tag);
143 | });
144 | ModchartUtilities.instance.setLuaFunction('setModEaseFunc', function(name:String, ease:String){
145 | setModEaseFunc(name,ease);
146 | });
147 | ModchartUtilities.instance.setLuaFunction('setModifier', function(beat:Float, argsAsString:String){
148 | set(beat, argsAsString);
149 | });
150 | ModchartUtilities.instance.setLuaFunction('easeModifier', function(beat:Float, time:Float, easeStr:String, argsAsString:String, ?tag:String = null){
151 | ease(beat, time, easeStr, argsAsString, null, tag);
152 | });
153 | ModchartUtilities.instance.setLuaFunction('ease', function(beat:Float, time:Float, easeStr:String, argsAsString:String, ?tag:String = null){
154 | ease(beat, time, easeStr, argsAsString, null, tag);
155 | });
156 | }
157 | #end
158 | }
159 |
160 |
161 | public static function loadHaxeFunctions(#if PSYCH funkin:FunkinLua#end)
162 | {
163 | #if (PSYCH && PSYCHVERSION >= "0.7")
164 | #if HSCRIPT_ALLOWED
165 | FunkinHScript.initHaxeModule(funkin);
166 |
167 | if (funkin.hscript != null)
168 | {
169 | #if (SScript >= "6.1.80")
170 | funkin.hscript.setClass(Math);
171 | funkin.hscript.setClass(PlayfieldRenderer);
172 | funkin.hscript.setClass(ModchartUtil);
173 | funkin.hscript.setClass(Modifier);
174 | funkin.hscript.setClass(NoteMovement);
175 | funkin.hscript.setClass(NotePositionData);
176 | funkin.hscript.setClass(ModchartFile);
177 | #else
178 | funkin.hscript.set('Math', Math);
179 | funkin.hscript.set('PlayfieldRenderer', PlayfieldRenderer);
180 | funkin.hscript.set('ModchartUtil', ModchartUtil);
181 | funkin.hscript.set('Modifier', Modifier);
182 | funkin.hscript.set('NoteMovement', NoteMovement);
183 | funkin.hscript.set('NotePositionData', NotePositionData);
184 | funkin.hscript.set('ModchartFile', ModchartFile);
185 | #end
186 | }
187 | #end
188 | #elseif LEATHER
189 | /*if(flixel.FlxG.state == states.PlayState.instance){
190 | HScript.instance.interp.variables.set('PlayfieldRenderer', PlayfieldRenderer);
191 | HScript.instance.interp.variables.set('ModchartUtil', ModchartUtil);
192 | HScript.instance.interp.variables.set('Modifier', Modifier);
193 | HScript.instance.interp.variables.set('NoteMovement', NoteMovement);
194 | HScript.instance.interp.variables.set('NotePositionData', NotePositionData);
195 | HScript.instance.interp.variables.set('ModchartFile', ModchartFile);
196 | }*/
197 | #end
198 | }
199 | #if (HSCRIPT_ALLOWED && PSYCH && PSYCHVERSION >= "0.7")
200 | public static function loadHScriptFunctions(parent:Dynamic)
201 | {
202 | #if HSCRIPT_ALLOWED
203 | parent.set('startMod', function(name:String, modClass:String, type:String = '', pf:Int = -1){
204 | startMod(name, modClass, type, pf);
205 |
206 | if (PlayState.instance == FlxG.state && PlayState.instance.playfieldRenderer != null)
207 | {
208 | PlayState.instance.playfieldRenderer.modifierTable.reconstructTable(); //needs to be reconstructed for lua modcharts
209 | }
210 | });
211 | parent.set('setMod', function(name:String, value:Float){
212 | setMod(name, value);
213 | });
214 | parent.set('setSubMod', function(name:String, subValName:String, value:Float){
215 | setSubMod(name, subValName,value);
216 | });
217 | parent.set('setModTargetLane', function(name:String, value:Int){
218 | setModTargetLane(name, value);
219 | });
220 | parent.set('setModPlayfield', function(name:String, value:Int){
221 | setModPlayfield(name,value);
222 | });
223 | parent.set('addPlayfield', function(?x:Float = 0, ?y:Float = 0, ?z:Float = 0){
224 | addPlayfield(x,y,z);
225 | });
226 | parent.set('removePlayfield', function(idx:Int){
227 | removePlayfield(idx);
228 | });
229 | parent.set('tweenModifier', function(modifier:String, val:Float, time:Float, ease:String, ?tag:String = null){
230 | tweenModifier(modifier,val,time,ease,null,tag);
231 | });
232 | parent.set('tweenModifierSubValue', function(modifier:String, subValue:String, val:Float, time:Float, ease:String, ?tag:String = null){
233 | tweenModifierSubValue(modifier,subValue,val,time,ease,null,tag);
234 | });
235 | parent.set('setModEaseFunc', function(name:String, ease:String, ?tag:String = null){
236 | setModEaseFunc(name,ease);
237 | });
238 | parent.set('setModValue', function(beat:Float, argsAsString:String){
239 | set(beat, argsAsString);
240 | });
241 | parent.set('easeModValue', function(beat:Float, time:Float, easeStr:String, argsAsString:String, ?tag:String = null){
242 | ease(beat, time, easeStr, argsAsString, null, tag);
243 | });
244 | #end
245 | }
246 | #end
247 |
248 | public static function startMod(name:String, modClass:String, type:String = '', pf:Int = -1, ?instance:ModchartMusicBeatState = null)
249 | {
250 | if (instance == null)
251 | {
252 | instance = PlayState.instance;
253 | if (instance.playfieldRenderer.modchart != null)
254 | if (instance.playfieldRenderer.modchart.scriptListen)
255 | {
256 | instance.playfieldRenderer.modchart.data.modifiers.push([name, modClass, type, pf]);
257 | trace(name,modClass,type,pf);
258 | }
259 | }
260 |
261 | if (instance.playfieldRenderer.modchart != null)
262 | if (instance.playfieldRenderer.modchart.customModifiers.exists(modClass))
263 | {
264 | var modifier = new Modifier(name, getModTypeFromString(type), pf);
265 | if (instance.playfieldRenderer.modchart.customModifiers.get(modClass).interp != null)
266 | instance.playfieldRenderer.modchart.customModifiers.get(modClass).interp.variables.set('instance', instance);
267 | instance.playfieldRenderer.modchart.customModifiers.get(modClass).initMod(modifier); //need to do it this way instead because using current value in the modifier script didnt work
268 | //var modifier = instance.playfieldRenderer.modchart.customModifiers.get(modClass).copy();
269 | //modifier.tag = name; //set correct stuff because its copying shit
270 | //modifier.playfield = pf;
271 | //modifier.type = getModTypeFromString(type);
272 | instance.playfieldRenderer.modifierTable.add(modifier);
273 | return;
274 | }
275 |
276 | var mod = Type.resolveClass('modcharting.'+modClass);
277 | if (mod == null) {mod = Type.resolveClass('modcharting.'+modClass+"Modifier");} //dont need to add "Modifier" to the end of every mod
278 |
279 | if (mod != null)
280 | {
281 | var modType = getModTypeFromString(type);
282 | var modifier = Type.createInstance(mod, [name, modType, pf]);
283 | instance.playfieldRenderer.modifierTable.add(modifier);
284 | }
285 | }
286 | public static function getModTypeFromString(type:String)
287 | {
288 | var modType = ModifierType.ALL;
289 | switch (type.toLowerCase())
290 | {
291 | case 'player':
292 | modType = ModifierType.PLAYERONLY;
293 | case 'opponent':
294 | modType = ModifierType.OPPONENTONLY;
295 | case 'lane' | 'lanespecific':
296 | modType = ModifierType.LANESPECIFIC;
297 | }
298 | return modType;
299 | }
300 |
301 | public static function setMod(name:String, value:Float, ?instance:ModchartMusicBeatState = null)
302 | {
303 | if (instance == null)
304 | instance = PlayState.instance;
305 | if (instance.playfieldRenderer.modchart != null)
306 | if (instance.playfieldRenderer.modchart.scriptListen)
307 | {
308 | instance.playfieldRenderer.modchart.data.events.push(["set", [0, value+","+name]]);
309 | }
310 | if (instance.playfieldRenderer.modifierTable.modifiers.exists(name))
311 | instance.playfieldRenderer.modifierTable.modifiers.get(name).currentValue = value;
312 | }
313 | public static function setSubMod(name:String, subValName:String, value:Float, ?instance:ModchartMusicBeatState = null)
314 | {
315 | if (instance == null)
316 | instance = PlayState.instance;
317 | if (instance.playfieldRenderer.modchart != null)
318 | if (instance.playfieldRenderer.modchart.scriptListen)
319 | {
320 | instance.playfieldRenderer.modchart.data.events.push(["set", [0, value+","+name+":"+subValName]]);
321 | }
322 | if (instance.playfieldRenderer.modifiers.exists(name))
323 | if (instance.playfieldRenderer.modifiers.get(name).subValues.exists(subValName))
324 | instance.playfieldRenderer.modifiers.get(name).subValues.get(subValName).value = value;
325 | else
326 | instance.playfieldRenderer.modifiers.get(name).subValues.set(subValName,new Modifier.ModifierSubValue(value));
327 | }
328 | public static function setModTargetLane(name:String, value:Int, ?instance:ModchartMusicBeatState = null)
329 | {
330 | if (instance == null)
331 | instance = PlayState.instance;
332 | if (instance.playfieldRenderer.modifierTable.modifiers.exists(name))
333 | instance.playfieldRenderer.modifierTable.modifiers.get(name).targetLane = value;
334 | }
335 | public static function setModPlayfield(name:String, value:Int, ?instance:ModchartMusicBeatState = null)
336 | {
337 | if (instance == null)
338 | instance = PlayState.instance;
339 | if (instance.playfieldRenderer.modifierTable.modifiers.exists(name))
340 | instance.playfieldRenderer.modifierTable.modifiers.get(name).playfield = value;
341 | }
342 | public static function addPlayfield(?x:Float = 0, ?y:Float = 0, ?z:Float = 0, ?instance:ModchartMusicBeatState = null)
343 | {
344 | if (instance == null)
345 | instance = PlayState.instance;
346 | instance.playfieldRenderer.addNewPlayfield(x,y,z);
347 | }
348 | public static function removePlayfield(idx:Int, ?instance:ModchartMusicBeatState = null)
349 | {
350 | if (instance == null)
351 | instance = PlayState.instance;
352 | instance.playfieldRenderer.playfields.remove(instance.playfieldRenderer.playfields[idx]);
353 | }
354 |
355 | public static function tweenModifier(modifier:String, val:Float, time:Float, ease:String, ?instance:ModchartMusicBeatState = null, ?tag:String = null)
356 | {
357 | if (instance == null)
358 | instance = PlayState.instance;
359 | instance.playfieldRenderer.modifierTable.tweenModifier(modifier, val, time, ease, Modifier.beat, tag);
360 | }
361 |
362 | public static function tweenModifierSubValue(modifier:String, subValue:String, val:Float, time:Float, ease:String, ?instance:ModchartMusicBeatState = null, ?tag:String = null)
363 | {
364 | if (instance == null)
365 | instance = PlayState.instance;
366 | instance.playfieldRenderer.modifierTable.tweenModifierSubValue(modifier, subValue, val, time, ease, Modifier.beat, tag);
367 | }
368 |
369 | public static function setModEaseFunc(name:String, ease:String, ?instance:ModchartMusicBeatState = null)
370 | {
371 | if (instance == null)
372 | instance = PlayState.instance;
373 | if (instance.playfieldRenderer.modifierTable.modifiers.exists(name))
374 | {
375 | var mod = instance.playfieldRenderer.modifierTable.modifiers.get(name);
376 | if (Std.isOfType(mod, EaseCurveModifier))
377 | {
378 | var temp:Dynamic = mod;
379 | var castedMod:EaseCurveModifier = temp;
380 | castedMod.setEase(ease);
381 | }
382 | }
383 | }
384 | public static function set(beat:Float, argsAsString:String, ?instance:ModchartMusicBeatState = null)
385 | {
386 | if (instance == null)
387 | {
388 | instance = PlayState.instance;
389 | if (instance.playfieldRenderer.modchart != null)
390 | if (instance.playfieldRenderer.modchart.scriptListen)
391 | {
392 | instance.playfieldRenderer.modchart.data.events.push(["set", [beat, argsAsString]]);
393 | }
394 | }
395 | var args = argsAsString.trim().replace(' ', '').split(',');
396 |
397 | instance.playfieldRenderer.eventManager.addEvent(beat, function(arguments:Array) {
398 | for (i in 0...Math.floor(arguments.length/2))
399 | {
400 | var name:String = Std.string(arguments[1 + (i*2)]);
401 | var value:Float = Std.parseFloat(arguments[0 + (i*2)]);
402 | if(Math.isNaN(value))
403 | value = 0;
404 | if (instance.playfieldRenderer.modifierTable.modifiers.exists(name))
405 | {
406 | instance.playfieldRenderer.modifierTable.modifiers.get(name).currentValue = value;
407 | }
408 | else
409 | {
410 | var subModCheck = name.split(':');
411 | if (subModCheck.length > 1)
412 | {
413 | var modName = subModCheck[0];
414 | var subModName = subModCheck[1];
415 | if (instance.playfieldRenderer.modifierTable.modifiers.exists(modName))
416 | instance.playfieldRenderer.modifierTable.modifiers.get(modName).subValues.get(subModName).value = value;
417 | }
418 | }
419 |
420 | }
421 | }, args);
422 | }
423 | public static function ease(beat:Float, time:Float, ease:String, argsAsString:String, ?instance:ModchartMusicBeatState = null, ?tag:String = null):Void
424 | {
425 | if (instance == null)
426 | {
427 | instance = PlayState.instance;
428 | if (instance.playfieldRenderer.modchart != null)
429 | if (instance.playfieldRenderer.modchart.scriptListen)
430 | {
431 | instance.playfieldRenderer.modchart.data.events.push(["ease", [beat, time, ease, argsAsString, tag]]);
432 | }
433 | }
434 |
435 | if(Math.isNaN(time))
436 | time = 1;
437 |
438 | var args = argsAsString.trim().replace(' ', '').split(',');
439 |
440 | var func = function(arguments:Array) {
441 |
442 | for (i in 0...Math.floor(arguments.length/2))
443 | {
444 | var name:String = Std.string(arguments[1 + (i*2)]);
445 | var value:Float = Std.parseFloat(arguments[0 + (i*2)]);
446 | if(Math.isNaN(value))
447 | value = 0;
448 | var subModCheck = name.split(':');
449 | if (subModCheck.length > 1)
450 | {
451 | var modName = subModCheck[0];
452 | var subModName = subModCheck[1];
453 | //trace(subModCheck);
454 | instance.playfieldRenderer.modifierTable.tweenModifierSubValue(modName, subModName, value, time*Conductor.crochet*0.001, ease, beat, tag);
455 | }
456 | else
457 | instance.playfieldRenderer.modifierTable.tweenModifier(name, value, time*Conductor.crochet*0.001, ease, beat, tag);
458 |
459 | }
460 | };
461 | instance.playfieldRenderer.eventManager.addEvent(beat, func, args);
462 | }
463 |
464 | }
465 |
--------------------------------------------------------------------------------
/source/modcharting/ModchartMusicBeatState.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | import flixel.addons.ui.FlxUIState;
4 | import modcharting.*;
5 | class ModchartMusicBeatState extends FlxUIState
6 | {
7 | //just stores the renderer so instancing shit can work properly i guess
8 | public var playfieldRenderer:PlayfieldRenderer;
9 | }
--------------------------------------------------------------------------------
/source/modcharting/ModchartUtil.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | import flixel.tweens.FlxEase;
4 | import flixel.math.FlxMath;
5 | import flixel.math.FlxAngle;
6 | import openfl.geom.Vector3D;
7 | import flixel.FlxG;
8 |
9 | #if LEATHER
10 | import states.PlayState;
11 | import game.Note;
12 | import game.Conductor;
13 | #elseif (PSYCH && PSYCHVERSION >= "0.7")
14 | import states.PlayState;
15 | import objects.Note;
16 | #else
17 | import PlayState;
18 | import Note;
19 | #end
20 |
21 | using StringTools;
22 |
23 | class ModchartUtil
24 | {
25 | public static function getDownscroll(instance:ModchartMusicBeatState)
26 | {
27 | //need to test each engine
28 | //not expecting all to work
29 | #if PSYCH
30 | #if (PSYCHVERSION >= "0.7")
31 | return ClientPrefs.downScroll;
32 | #else
33 | return ClientPrefs.data.downScroll;
34 | #end
35 | #elseif LEATHER
36 | return utilities.Options.getData("downscroll");
37 | #elseif ANDROMEDA //dunno why youd use this on andromeda but whatever, already got its own cool modchart system
38 | return instance.currentOptions.downScroll;
39 | #elseif KADE
40 | return PlayStateChangeables.useDownscroll;
41 | #elseif FOREVER_LEGACY //forever might not work just yet because of the multiple strumgroups
42 | return Init.trueSettings.get('Downscroll');
43 | #elseif FPSPLUS
44 | return Config.downscroll;
45 | #elseif MIC_D_UP //basically no one uses this anymore
46 | return MainVariables._variables.scroll == "down"
47 | #else
48 | return false;
49 | #end
50 | }
51 | public static function getMiddlescroll(instance:ModchartMusicBeatState)
52 | {
53 | #if PSYCH
54 | #if (PSYCHVERSION >= "0.7")
55 | return ClientPrefs.middleScroll;
56 | #else
57 | return ClientPrefs.data.middleScroll;
58 | #end
59 | #elseif LEATHER
60 | return utilities.Options.getData("middlescroll");
61 | #else
62 | return false;
63 | #end
64 | }
65 | public static function getScrollSpeed(instance:PlayState)
66 | {
67 | if (instance == null)
68 | return PlayState.SONG.speed;
69 |
70 | #if (PSYCH || ANDROMEDA)
71 | return instance.songSpeed;
72 | #elseif LEATHER
73 | @:privateAccess
74 | return instance.speed;
75 | #elseif KADE
76 | return PlayStateChangeables.scrollSpeed == 1 ? PlayState.SONG.speed : PlayStateChangeables.scrollSpeed;
77 | #else
78 | return PlayState.SONG.speed; //most engines just use this
79 | #end
80 | }
81 |
82 | public static function getIsPixelStage(instance:ModchartMusicBeatState)
83 | {
84 | if (instance == null)
85 | return false;
86 | #if LEATHER
87 | return PlayState.SONG.ui_Skin == 'pixel';
88 | #else
89 | return PlayState.isPixelStage;
90 | #end
91 | }
92 |
93 | public static function getNoteOffsetX(daNote:Note, instance:ModchartMusicBeatState)
94 | {
95 | #if PSYCH
96 | return daNote.offsetX;
97 | #elseif LEATHER
98 | //fuck
99 | var offset:Float = 0;
100 |
101 | var lane = daNote.noteData;
102 | if (daNote.mustPress)
103 | lane += NoteMovement.keyCount;
104 | var strum = instance.playfieldRenderer.strumGroup.members[lane];
105 |
106 | var arrayVal = Std.string([lane, daNote.arrow_Type, daNote.isSustainNote]);
107 |
108 | if (!NoteMovement.leatherEngineOffsetStuff.exists(arrayVal))
109 | {
110 | var tempShit:Float = 0.0;
111 |
112 |
113 | var targetX = NoteMovement.defaultStrumX[lane];
114 | var xPos = targetX;
115 | while (Std.int(xPos + (daNote.width / 2)) != Std.int(targetX + (strum.width / 2)))
116 | {
117 | xPos += (xPos + daNote.width > targetX + strum.width ? -0.1 : 0.1);
118 | tempShit += (xPos + daNote.width > targetX + strum.width ? -0.1 : 0.1);
119 | }
120 | //trace(arrayVal);
121 | //trace(tempShit);
122 |
123 | NoteMovement.leatherEngineOffsetStuff.set(arrayVal, tempShit);
124 | }
125 | offset = NoteMovement.leatherEngineOffsetStuff.get(arrayVal);
126 |
127 | return offset;
128 | #else
129 | return (daNote.isSustainNote ? 37 : 0); //the magic number
130 | #end
131 | }
132 |
133 | static var currentFakeCrochet:Float = -1;
134 | static var lastBpm:Float = -1;
135 |
136 | public static function getFakeCrochet()
137 | {
138 | if (PlayState.SONG.bpm != lastBpm)
139 | {
140 | currentFakeCrochet = (60 / PlayState.SONG.bpm) * 1000; //only need to calculate once
141 | lastBpm = PlayState.SONG.bpm;
142 | }
143 | return currentFakeCrochet;
144 |
145 | }
146 |
147 | public static var zNear:Float = 0;
148 | public static var zFar:Float = 100;
149 | public static var defaultFOV:Float = 90;
150 |
151 | /**
152 | Converts a Vector3D to its in world coordinates using perspective math
153 | **/
154 | public static function calculatePerspective(pos:Vector3D, FOV:Float, offsetX:Float = 0, offsetY:Float = 0)
155 | {
156 |
157 | /* math from opengl lol
158 | found from this website https://ogldev.org/www/tutorial12/tutorial12.html
159 | */
160 |
161 | //TODO: maybe try using actual matrix???
162 |
163 | var newz = pos.z - 1;
164 | var zRange = zNear - zFar;
165 | var tanHalfFOV = FlxMath.fastSin(FOV*0.5)/FlxMath.fastCos(FOV*0.5); //faster tan
166 | if (pos.z > 1) //if above 1000 z basically
167 | newz = 0; //should stop weird mirroring with high z values
168 |
169 | //var m00 = 1/(tanHalfFOV);
170 | //var m11 = 1/tanHalfFOV;
171 | //var m22 = (-zNear - zFar) / zRange; //isnt this just 1 lol
172 | //var m23 = 2 * zFar * zNear / zRange;
173 | //var m32 = 1;
174 |
175 | var xOffsetToCenter = pos.x - (FlxG.width*0.5); //so the perspective focuses on the center of the screen
176 | var yOffsetToCenter = pos.y - (FlxG.height*0.5);
177 |
178 | var zPerspectiveOffset = (newz+(2 * zFar * zNear / zRange));
179 |
180 |
181 | //xOffsetToCenter += (offsetX / (1/-zPerspectiveOffset));
182 | //yOffsetToCenter += (offsetY / (1/-zPerspectiveOffset));
183 | xOffsetToCenter += (offsetX * -zPerspectiveOffset);
184 | yOffsetToCenter += (offsetY * -zPerspectiveOffset);
185 |
186 | var xPerspective = xOffsetToCenter*(1/tanHalfFOV);
187 | var yPerspective = yOffsetToCenter*tanHalfFOV;
188 | xPerspective /= -zPerspectiveOffset;
189 | yPerspective /= -zPerspectiveOffset;
190 |
191 | pos.x = xPerspective+(FlxG.width*0.5); //offset it back to normal
192 | pos.y = yPerspective+(FlxG.height*0.5);
193 | pos.z = zPerspectiveOffset;
194 |
195 |
196 |
197 | //pos.z -= 1;
198 | //pos = perspectiveMatrix.transformVector(pos);
199 |
200 | return pos;
201 | }
202 | /**
203 | Returns in-world 3D coordinates using polar angle, azimuthal angle and a radius.
204 | (Spherical to Cartesian)
205 |
206 | @param theta Angle used along the polar axis.
207 | @param phi Angle used along the azimuthal axis.
208 | @param radius Distance to center.
209 | **/
210 | public static function getCartesianCoords3D(theta:Float, phi:Float, radius:Float):Vector3D
211 | {
212 | var pos:Vector3D = new Vector3D();
213 | var rad = FlxAngle.TO_RAD;
214 | pos.x = FlxMath.fastCos(theta*rad)*FlxMath.fastSin(phi*rad);
215 | pos.y = FlxMath.fastCos(phi*rad);
216 | pos.z = FlxMath.fastSin(theta*rad)*FlxMath.fastSin(phi*rad);
217 | pos.x *= radius;
218 | pos.y *= radius;
219 | pos.z *= radius;
220 |
221 | return pos;
222 | }
223 |
224 | public static function getFlxEaseByString(?ease:String = '') {
225 | switch(ease.toLowerCase().trim()) {
226 | case 'backin': return FlxEase.backIn;
227 | case 'backinout': return FlxEase.backInOut;
228 | case 'backout': return FlxEase.backOut;
229 | case 'bouncein': return FlxEase.bounceIn;
230 | case 'bounceinout': return FlxEase.bounceInOut;
231 | case 'bounceout': return FlxEase.bounceOut;
232 | case 'circin': return FlxEase.circIn;
233 | case 'circinout': return FlxEase.circInOut;
234 | case 'circout': return FlxEase.circOut;
235 | case 'cubein': return FlxEase.cubeIn;
236 | case 'cubeinout': return FlxEase.cubeInOut;
237 | case 'cubeout': return FlxEase.cubeOut;
238 | case 'elasticin': return FlxEase.elasticIn;
239 | case 'elasticinout': return FlxEase.elasticInOut;
240 | case 'elasticout': return FlxEase.elasticOut;
241 | case 'expoin': return FlxEase.expoIn;
242 | case 'expoinout': return FlxEase.expoInOut;
243 | case 'expoout': return FlxEase.expoOut;
244 | case 'quadin': return FlxEase.quadIn;
245 | case 'quadinout': return FlxEase.quadInOut;
246 | case 'quadout': return FlxEase.quadOut;
247 | case 'quartin': return FlxEase.quartIn;
248 | case 'quartinout': return FlxEase.quartInOut;
249 | case 'quartout': return FlxEase.quartOut;
250 | case 'quintin': return FlxEase.quintIn;
251 | case 'quintinout': return FlxEase.quintInOut;
252 | case 'quintout': return FlxEase.quintOut;
253 | case 'sinein': return FlxEase.sineIn;
254 | case 'sineinout': return FlxEase.sineInOut;
255 | case 'sineout': return FlxEase.sineOut;
256 | case 'smoothstepin': return FlxEase.smoothStepIn;
257 | case 'smoothstepinout': return FlxEase.smoothStepInOut;
258 | case 'smoothstepout': return FlxEase.smoothStepInOut;
259 | case 'smootherstepin': return FlxEase.smootherStepIn;
260 | case 'smootherstepinout': return FlxEase.smootherStepInOut;
261 | case 'smootherstepout': return FlxEase.smootherStepOut;
262 | }
263 | return FlxEase.linear;
264 | }
265 |
266 |
267 | public static function getTimeFromBeat(beat:Float)
268 | {
269 | var totalTime:Float = 0;
270 | var curBpm = Conductor.bpm;
271 | if (PlayState.SONG != null)
272 | curBpm = PlayState.SONG.bpm;
273 | for (i in 0...Math.floor(beat))
274 | {
275 | if (Conductor.bpmChangeMap.length > 0)
276 | {
277 | for (j in 0...Conductor.bpmChangeMap.length)
278 | {
279 | if (totalTime >= Conductor.bpmChangeMap[j].songTime)
280 | curBpm = Conductor.bpmChangeMap[j].bpm;
281 | }
282 | }
283 | totalTime += (60/curBpm)*1000;
284 | }
285 |
286 | var leftOverBeat = beat - Math.floor(beat);
287 | totalTime += (60/curBpm)*1000*leftOverBeat;
288 |
289 | return totalTime;
290 | }
291 | }
--------------------------------------------------------------------------------
/source/modcharting/NoteMovement.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | #if LEATHER
4 | import states.PlayState;
5 | import game.Note;
6 | #elseif (PSYCH && PSYCHVERSION >= "0.7")
7 | import states.PlayState;
8 | import objects.Note;
9 | #else
10 | import PlayState;
11 | import Note;
12 | #end
13 |
14 | using StringTools;
15 |
16 | class NoteMovement
17 | {
18 | public static var keyCount = 4;
19 | public static var playerKeyCount = 4;
20 | public static var totalKeyCount = 8;
21 | public static var arrowScale:Float = 0.7;
22 | public static var arrowSize:Float = 112;
23 | public static var defaultStrumX:Array = [];
24 | public static var defaultStrumY:Array = [];
25 | public static var defaultSkewX:Array = [];
26 | public static var defaultSkewY:Array = [];
27 | public static var defaultScale:Array = [];
28 | public static var arrowSizes:Array = [];
29 | #if LEATHER
30 | public static var leatherEngineOffsetStuff:Map = [];
31 | #end
32 |
33 | public static function getDefaultStrumPos(game:PlayState)
34 | {
35 | defaultStrumX = []; //reset
36 | defaultStrumY = [];
37 | defaultSkewX = [];
38 | defaultSkewY = [];
39 | defaultScale = [];
40 | arrowSizes = [];
41 | keyCount = #if (LEATHER || KADE) PlayState.strumLineNotes.length-PlayState.playerStrums.length #else game.strumLineNotes.length-game.playerStrums.length #end; //base game doesnt have opponent strums as group
42 | playerKeyCount = #if (LEATHER || KADE) PlayState.playerStrums.length #else game.playerStrums.length #end;
43 |
44 | for (i in #if (LEATHER || KADE) 0...PlayState.strumLineNotes.members.length #else 0...game.strumLineNotes.members.length #end)
45 | {
46 | #if (LEATHER || KADE)
47 | var strum = PlayState.strumLineNotes.members[i];
48 | #else
49 | var strum = game.strumLineNotes.members[i];
50 | #end
51 | defaultSkewX.push(strum.skew.x);
52 | defaultSkewY.push(strum.skew.y);
53 | defaultStrumX.push(strum.x);
54 | defaultStrumY.push(strum.y);
55 | #if LEATHER
56 | var localKeyCount = (i < keyCount ? keyCount : playerKeyCount);
57 | var s = Std.parseFloat(game.ui_settings[0]) * (Std.parseFloat(game.ui_settings[2]) - (Std.parseFloat(game.mania_size[localKeyCount-1])));
58 | #else
59 | var s = 0.7;
60 | #end
61 |
62 | defaultScale.push(s);
63 | arrowSizes.push(160*s);
64 | }
65 | #if LEATHER
66 | leatherEngineOffsetStuff.clear();
67 | #end
68 | totalKeyCount = keyCount + playerKeyCount;
69 | }
70 | public static function getDefaultStrumPosEditor(game:modcharting.ModchartEditorState)
71 | {
72 | #if ((PSYCH || LEATHER) && !DISABLE_MODCHART_EDITOR)
73 | defaultStrumX = []; //reset
74 | defaultStrumY = [];
75 | defaultSkewX = [];
76 | defaultSkewY = [];
77 | defaultScale = [];
78 | arrowSizes = [];
79 | keyCount = game.strumLineNotes.length-game.playerStrums.length; //base game doesnt have opponent strums as group
80 | playerKeyCount = game.playerStrums.length;
81 |
82 |
83 | for (i in 0...game.strumLineNotes.members.length)
84 | {
85 | var strum = game.strumLineNotes.members[i];
86 | defaultSkewX.push(strum.skew.x);
87 | defaultSkewY.push(strum.skew.y);
88 | defaultStrumX.push(strum.x);
89 | defaultStrumY.push(strum.y);
90 | #if LEATHER
91 | var localKeyCount = (i < keyCount ? keyCount : playerKeyCount);
92 | var s = Std.parseFloat(game.ui_settings[0]) * (Std.parseFloat(game.ui_settings[2]) - (Std.parseFloat(game.mania_size[localKeyCount-1])));
93 | #else
94 | var s = 0.7;
95 | #end
96 |
97 | defaultScale.push(s);
98 | arrowSizes.push(160*s);
99 | }
100 | #end
101 | #if LEATHER
102 | leatherEngineOffsetStuff.clear();
103 | #end
104 | }
105 | public static function setNotePath(daNote:Note, lane:Int, scrollSpeed:Float, curPos:Float, noteDist:Float, incomingAngleX:Float, incomingAngleY:Float)
106 | {
107 | daNote.x = defaultStrumX[lane];
108 | daNote.y = defaultStrumY[lane];
109 | daNote.z = 0;
110 |
111 | var pos = ModchartUtil.getCartesianCoords3D(incomingAngleX,incomingAngleY, curPos*noteDist);
112 | daNote.y += pos.y;
113 | daNote.x += pos.x;
114 | daNote.z += pos.z;
115 |
116 | daNote.skew.x = defaultSkewX[lane];
117 | daNote.skew.y = defaultSkewY[lane];
118 | }
119 |
120 | public static function getLaneDiffFromCenter(lane:Int)
121 | {
122 | var col:Float = lane%4;
123 | if ((col+1) > (keyCount*0.5))
124 | {
125 | col -= (keyCount*0.5)+1;
126 | }
127 | else
128 | {
129 | col -= (keyCount*0.5);
130 | }
131 |
132 | //col = (col-col-col); //flip pos/negative
133 |
134 | //trace(col);
135 |
136 | return col;
137 | }
138 |
139 |
140 | }
141 |
142 |
--------------------------------------------------------------------------------
/source/modcharting/NotePositionData.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | import flixel.util.FlxDestroyUtil.IFlxDestroyable;
4 | import flixel.util.FlxPool;
5 |
6 | class NotePositionData implements IFlxDestroyable
7 | {
8 | static var pool:FlxPool = new FlxPool(NotePositionData);
9 |
10 | public var x:Float;
11 | public var y:Float;
12 | public var z:Float;
13 | public var angle:Float;
14 | public var alpha:Float;
15 | public var scaleX:Float;
16 | public var scaleY:Float;
17 | public var skewX:Float;
18 | public var skewY:Float;
19 | public var curPos:Float;
20 | public var noteDist:Float;
21 | public var lane:Int;
22 | public var index:Int;
23 | public var playfieldIndex:Int;
24 | public var isStrum:Bool;
25 | public var incomingAngleX:Float;
26 | public var incomingAngleY:Float;
27 | public var strumTime:Float;
28 | public function new() {}
29 | public function destroy() {}
30 | public static function get() : NotePositionData
31 | {
32 | return pool.get();
33 | }
34 |
35 | public function setupStrum(x:Float, y:Float, z:Float, lane:Int, scaleX:Float, scaleY:Float, skewX:Float, skewY:Float, pf:Int)
36 | {
37 | this.x = x;
38 | this.y = y;
39 | this.z = z;
40 | this.angle = 0;
41 | this.alpha = 1;
42 | this.scaleX = scaleX;
43 | this.scaleY = scaleY;
44 | this.skewX = skewX;
45 | this.skewY = skewY;
46 | this.index = lane;
47 | this.playfieldIndex = pf;
48 | this.lane = lane;
49 | this.curPos = 0;
50 | this.noteDist = 0;
51 | this.isStrum = true;
52 | this.incomingAngleX = 0;
53 | this.incomingAngleY = 0;
54 | this.strumTime = 0;
55 | }
56 |
57 | public function setupNote(x:Float, y:Float, z:Float, lane:Int, scaleX:Float, scaleY:Float, skewX:Float, skewY:Float, pf:Int, alpha:Float, curPos:Float, noteDist:Float, iaX:Float, iaY:Float, strumTime:Float, index:Int)
58 | {
59 | this.x = x;
60 | this.y = y;
61 | this.z = z;
62 | this.angle = 0;
63 | this.alpha = alpha;
64 | this.scaleX = scaleX;
65 | this.scaleY = scaleY;
66 | this.skewX = skewX;
67 | this.skewY = skewY;
68 | this.index = index;
69 | this.playfieldIndex = pf;
70 | this.lane = lane;
71 | this.curPos = curPos;
72 | this.noteDist = noteDist;
73 | this.isStrum = false;
74 | this.incomingAngleX = iaX;
75 | this.incomingAngleY = iaY;
76 | this.strumTime = strumTime;
77 | }
78 | }
--------------------------------------------------------------------------------
/source/modcharting/Playfield.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | class Playfield
4 | {
5 | public var x:Float = 0;
6 | public var y:Float = 0;
7 | public var z:Float = 0;
8 | public var alpha:Float = 1;
9 |
10 | public function new(x:Float = 0, y:Float = 0, z:Float = 0, alpha:Float = 1)
11 | {
12 | this.x = x;
13 | this.y = y;
14 | this.z = z;
15 | this.alpha = alpha;
16 | }
17 |
18 | public function applyOffsets(noteData:NotePositionData)
19 | {
20 | noteData.x += x;
21 | noteData.y += y;
22 | noteData.z += z;
23 | noteData.alpha *= alpha;
24 | }
25 | }
--------------------------------------------------------------------------------
/source/modcharting/PlayfieldRenderer.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | import flixel.tweens.misc.BezierPathTween;
4 | import flixel.tweens.misc.BezierPathNumTween;
5 | import flixel.util.FlxTimer.FlxTimerManager;
6 | import flixel.math.FlxMath;
7 | import flixel.tweens.FlxTween;
8 | import flixel.tweens.FlxEase;
9 | import flixel.graphics.FlxGraphic;
10 | import flixel.util.FlxColor;
11 | import flixel.FlxStrip;
12 | import flixel.graphics.tile.FlxDrawTrianglesItem.DrawData;
13 | import openfl.geom.Vector3D;
14 | import flixel.util.FlxSpriteUtil;
15 | import flixel.graphics.frames.FlxFrame;
16 | import flixel.group.FlxGroup.FlxTypedGroup;
17 | import flixel.FlxSprite;
18 |
19 | import flixel.FlxG;
20 | import modcharting.Modifier;
21 | import managers.*;
22 | import flixel.system.FlxAssets.FlxShader;
23 | import managers.TweenManager;
24 |
25 | #if LEATHER
26 | import states.PlayState;
27 | import game.Note;
28 | import game.StrumNote;
29 | import game.Conductor;
30 | #elseif (PSYCH && PSYCHVERSION >= "0.7")
31 | import states.PlayState;
32 | import objects.Note;
33 | import objects.StrumNote;
34 | #else
35 | import PlayState;
36 | import Note;
37 | import StrumNote;
38 | #end
39 |
40 | using StringTools;
41 |
42 | //a few todos im gonna leave here:
43 |
44 | //setup quaternions for everything else (incoming angles and the rotate mod)
45 | //do add and remove buttons on stacked events in editor
46 | //fix switching event type in editor so you can actually do set events
47 | //finish setting up tooltips in editor
48 | //start documenting more stuff idk
49 |
50 | typedef StrumNoteType =
51 | #if (PSYCH || LEATHER) StrumNote
52 | #elseif KADE StaticArrow
53 | #elseif FOREVER_LEGACY UIStaticArrow
54 | #elseif ANDROMEDA Receptor
55 | #else FlxSprite #end;
56 |
57 | class PlayfieldRenderer extends FlxSprite //extending flxsprite just so i can edit draw
58 | {
59 | public var strumGroup:FlxTypedGroup;
60 | public var notes:FlxTypedGroup;
61 | public var instance:ModchartMusicBeatState;
62 | public var playStateInstance:PlayState;
63 | public var playfields:Array = []; //adding an extra playfield will add 1 for each player
64 |
65 | public var eventManager:ModchartEventManager;
66 | public var modifierTable:ModTable;
67 | public var tweenManager:TweenManager = null;
68 | public var timerManager:FlxTimerManager = null;
69 |
70 | public var modchart:ModchartFile;
71 | public var inEditor:Bool = false;
72 | public var editorPaused:Bool = false;
73 |
74 | public var speed:Float = 1.0;
75 |
76 | public var modifiers(get, default):Map;
77 |
78 | private function get_modifiers() : Map
79 | {
80 | return modifierTable.modifiers; //back compat with lua modcharts
81 | }
82 |
83 |
84 | public function new(strumGroup:FlxTypedGroup, notes:FlxTypedGroup,instance:ModchartMusicBeatState)
85 | {
86 | super(0,0);
87 | this.strumGroup = strumGroup;
88 | this.notes = notes;
89 | this.instance = instance;
90 | if (Std.isOfType(instance, PlayState))
91 | playStateInstance = cast instance; //so it just casts once
92 |
93 | strumGroup.visible = false; //drawing with renderer instead
94 | notes.visible = false;
95 |
96 | //fix stupid crash because the renderer in playstate is still technically null at this point and its needed for json loading
97 | instance.playfieldRenderer = this;
98 |
99 | tweenManager = new TweenManager();
100 | timerManager = new FlxTimerManager();
101 | eventManager = new ModchartEventManager(this);
102 | modifierTable = new ModTable(instance, this);
103 | addNewPlayfield(0,0,0);
104 | modchart = new ModchartFile(this);
105 | }
106 |
107 |
108 | public function addNewPlayfield(?x:Float = 0, ?y:Float = 0, ?z:Float = 0, ?alpha:Float = 1)
109 | {
110 | playfields.push(new Playfield(x,y,z,alpha));
111 | }
112 |
113 | override function update(elapsed:Float)
114 | {
115 | try {
116 | eventManager.update(elapsed);
117 | tweenManager.update(elapsed); //should be automatically paused when you pause in game
118 | timerManager.update(elapsed);
119 | } catch(e) {
120 | trace(e);
121 | }
122 | super.update(elapsed);
123 | }
124 |
125 |
126 | override public function draw()
127 | {
128 | if (alpha == 0 || !visible)
129 | return;
130 |
131 | strumGroup.cameras = this.cameras;
132 | notes.cameras = this.cameras;
133 |
134 | try {
135 | drawStuff(getNotePositions());
136 | } catch(e) {
137 | trace(e);
138 | }
139 | //draw notes to screen
140 | }
141 |
142 |
143 | private function addDataToStrum(strumData:NotePositionData, strum:StrumNoteType)
144 | {
145 | strum.x = strumData.x;
146 | strum.y = strumData.y;
147 | //Add Z to your strumNoteType if you want it youself!
148 | //strum.z = strumData.z;
149 | strum.angle = strumData.angle;
150 | strum.alpha = strumData.alpha;
151 | strum.scale.x = strumData.scaleX;
152 | strum.scale.y = strumData.scaleY;
153 | strum.skew.x = strumData.skewX;
154 | strum.skew.y = strumData.skewY;
155 | }
156 |
157 | private function getDataForStrum(i:Int, pf:Int)
158 | {
159 | var strumX = NoteMovement.defaultStrumX[i];
160 | var strumY = NoteMovement.defaultStrumY[i];
161 | var strumZ = 0;
162 | var strumScaleX = NoteMovement.defaultScale[i];
163 | var strumScaleY = NoteMovement.defaultScale[i];
164 | var strumSkewX = NoteMovement.defaultSkewX[i];
165 | var strumSkewY = NoteMovement.defaultSkewY[i];
166 | if (ModchartUtil.getIsPixelStage(instance))
167 | {
168 | //work on pixel stages
169 | strumScaleX = 1*PlayState.daPixelZoom;
170 | strumScaleY = 1*PlayState.daPixelZoom;
171 | }
172 | var strumData:NotePositionData = NotePositionData.get();
173 | strumData.setupStrum(strumX, strumY, strumZ, i, strumScaleX, strumScaleY, strumSkewX, strumSkewY, pf);
174 | playfields[pf].applyOffsets(strumData);
175 | modifierTable.applyStrumMods(strumData, i, pf);
176 | return strumData;
177 | }
178 |
179 |
180 |
181 | private function addDataToNote(noteData:NotePositionData, daNote:Note)
182 | {
183 | daNote.x = noteData.x;
184 | daNote.y = noteData.y;
185 | daNote.z = noteData.z;
186 | daNote.angle = noteData.angle;
187 | daNote.alpha = noteData.alpha;
188 | daNote.scale.x = noteData.scaleX;
189 | daNote.scale.y = noteData.scaleY;
190 | daNote.skew.x = noteData.skewX;
191 | daNote.skew.y = noteData.skewY;
192 | }
193 | private function createDataFromNote(noteIndex:Int, playfieldIndex:Int, curPos:Float, noteDist:Float, incomingAngle:Array)
194 | {
195 | var noteX = notes.members[noteIndex].x;
196 | var noteY = notes.members[noteIndex].y;
197 | var noteZ = notes.members[noteIndex].z;
198 | var lane = getLane(noteIndex);
199 | var noteScaleX = NoteMovement.defaultScale[lane];
200 | var noteScaleY = NoteMovement.defaultScale[lane];
201 | var noteSkewX = notes.members[noteIndex].skew.x;
202 | var noteSkewY = notes.members[noteIndex].skew.y;
203 |
204 | var noteAlpha:Float = #if PSYCH notes.members[noteIndex].multAlpha; #else notes.members[noteIndex].isSustainNote ? 0.6 : 1; #end
205 |
206 | if (ModchartUtil.getIsPixelStage(instance))
207 | {
208 | //work on pixel stages
209 | noteScaleX = 1*PlayState.daPixelZoom;
210 | noteScaleY = 1*PlayState.daPixelZoom;
211 | }
212 |
213 | var noteData:NotePositionData = NotePositionData.get();
214 | noteData.setupNote(noteX, noteY, noteZ, lane, noteScaleX, noteScaleY, noteSkewX, noteSkewY, playfieldIndex, noteAlpha,
215 | curPos, noteDist, incomingAngle[0], incomingAngle[1], notes.members[noteIndex].strumTime, noteIndex);
216 | playfields[playfieldIndex].applyOffsets(noteData);
217 | return noteData;
218 | }
219 |
220 | private function getNoteCurPos(noteIndex:Int, strumTimeOffset:Float = 0)
221 | {
222 | #if PSYCH
223 | if (notes.members[noteIndex].isSustainNote && ModchartUtil.getDownscroll(instance))
224 | strumTimeOffset -= Std.int(Conductor.stepCrochet/getCorrectScrollSpeed()); //psych does this to fix its sustains but that breaks the visuals so basically reverse it back to normal
225 | #else
226 | if (notes.members[noteIndex].isSustainNote && !ModchartUtil.getDownscroll(instance))
227 | strumTimeOffset += Conductor.stepCrochet; //fix upscroll lol
228 | #end
229 | var distance = (Conductor.songPosition - notes.members[noteIndex].strumTime) + strumTimeOffset;
230 | return distance*getCorrectScrollSpeed();
231 | }
232 | private function getLane(noteIndex:Int)
233 | {
234 | return (notes.members[noteIndex].mustPress ? notes.members[noteIndex].noteData+NoteMovement.keyCount : notes.members[noteIndex].noteData);
235 | }
236 | private function getNoteDist(noteIndex:Int)
237 | {
238 | var noteDist = -0.45;
239 | if (ModchartUtil.getDownscroll(instance))
240 | noteDist *= -1;
241 | return noteDist;
242 | }
243 |
244 |
245 | private function getNotePositions()
246 | {
247 | var notePositions:Array = [];
248 | for (pf in 0...playfields.length)
249 | {
250 | for (i in 0...strumGroup.members.length)
251 | {
252 | var strumData = getDataForStrum(i, pf);
253 | notePositions.push(strumData);
254 | }
255 | for (i in 0...notes.members.length)
256 | {
257 | var songSpeed = getCorrectScrollSpeed();
258 |
259 | var lane = getLane(i);
260 |
261 | var noteDist = getNoteDist(i);
262 | noteDist = modifierTable.applyNoteDistMods(noteDist, lane, pf);
263 |
264 | var sustainTimeThingy:Float = 0;
265 |
266 | //just causes too many issues lol, might fix it at some point
267 | /*if (notes.members[i].animation.curAnim.name.endsWith('end') && ClientPrefs.downScroll)
268 | {
269 | if (noteDist > 0)
270 | sustainTimeThingy = (NoteMovement.getFakeCrochet()/4)/2; //fix stretched sustain ends (downscroll)
271 | //else
272 | //sustainTimeThingy = (-NoteMovement.getFakeCrochet()/4)/songSpeed;
273 | }*/
274 |
275 | var curPos = getNoteCurPos(i, sustainTimeThingy);
276 | curPos = modifierTable.applyCurPosMods(lane, curPos, pf);
277 |
278 | if ((notes.members[i].wasGoodHit || (notes.members[i].prevNote.wasGoodHit)) && curPos >= 0 && notes.members[i].isSustainNote)
279 | curPos = 0; //sustain clip
280 |
281 | var incomingAngle:Array = modifierTable.applyIncomingAngleMods(lane, curPos, pf);
282 | if (noteDist < 0)
283 | incomingAngle[0] += 180; //make it match for both scrolls
284 |
285 | //get the general note path
286 | NoteMovement.setNotePath(notes.members[i], lane, songSpeed, curPos, noteDist, incomingAngle[0], incomingAngle[1]);
287 |
288 | //save the position data
289 | var noteData = createDataFromNote(i, pf, curPos, noteDist, incomingAngle);
290 |
291 | //add offsets to data with modifiers
292 | modifierTable.applyNoteMods(noteData, lane, curPos, pf);
293 |
294 | //add position data to list
295 | notePositions.push(noteData);
296 | }
297 | }
298 | //sort by z before drawing
299 | notePositions.sort(function(a, b){
300 | if (a.z < b.z)
301 | return -1;
302 | else if (a.z > b.z)
303 | return 1;
304 | else
305 | return 0;
306 | });
307 | return notePositions;
308 | }
309 |
310 | private function drawStrum(noteData:NotePositionData)
311 | {
312 | if (noteData.alpha <= 0)
313 | return;
314 | var changeX:Bool = ((noteData.z > 0 || noteData.z < 0) && noteData.z != 0);
315 | var strumNote = strumGroup.members[noteData.index];
316 | var thisNotePos = changeX ?
317 | ModchartUtil.calculatePerspective(new Vector3D(noteData.x+(strumNote.width/2), noteData.y+(strumNote.height/2), noteData.z*0.001),
318 | ModchartUtil.defaultFOV*(Math.PI/180), -(strumNote.width/2), -(strumNote.height/2))
319 | : new Vector3D(noteData.x, noteData.y, 0);
320 |
321 | noteData.x = thisNotePos.x;
322 | noteData.y = thisNotePos.y;
323 | if (changeX) {
324 | noteData.scaleX *= (1/-thisNotePos.z);
325 | noteData.scaleY *= (1/-thisNotePos.z);
326 | }
327 | // noteData.skewX = skewX + noteData.skewX;
328 | // noteData.skewY = skewY + noteData.skewY;
329 |
330 | addDataToStrum(noteData, strumGroup.members[noteData.index]); //set position and stuff before drawing
331 | strumGroup.members[noteData.index].cameras = this.cameras;
332 |
333 | strumGroup.members[noteData.index].draw();
334 | }
335 | private function drawNote(noteData:NotePositionData)
336 | {
337 | if (noteData.alpha <= 0)
338 | return;
339 | var changeX:Bool = ((noteData.z > 0 || noteData.z < 0) && noteData.z != 0);
340 | var daNote = notes.members[noteData.index];
341 | var thisNotePos = changeX ?
342 | ModchartUtil.calculatePerspective(new Vector3D(noteData.x+(daNote.width/2)+ModchartUtil.getNoteOffsetX(daNote, instance), noteData.y+(daNote.height/2), noteData.z*0.001),
343 | ModchartUtil.defaultFOV*(Math.PI/180), -(daNote.width/2), -(daNote.height/2))
344 | : new Vector3D(noteData.x, noteData.y, 0);
345 |
346 | noteData.x = thisNotePos.x;
347 | noteData.y = thisNotePos.y;
348 | if (changeX) {
349 | noteData.scaleX *= (1/-thisNotePos.z);
350 | noteData.scaleY *= (1/-thisNotePos.z);
351 | }
352 | // noteData.skewX = skewX + noteData.skewX;
353 | // noteData.skewY = skewY + noteData.skewY;
354 | //set note position using the position data
355 | addDataToNote(noteData, notes.members[noteData.index]);
356 | //make sure it draws on the correct camera
357 | notes.members[noteData.index].cameras = this.cameras;
358 | //draw it
359 | notes.members[noteData.index].draw();
360 | }
361 | private function drawSustainNote(noteData:NotePositionData)
362 | {
363 | if (noteData.alpha <= 0)
364 | return;
365 | var daNote = notes.members[noteData.index];
366 | if (daNote.mesh == null)
367 | daNote.mesh = new SustainStrip(daNote);
368 |
369 | daNote.mesh.scrollFactor.x = daNote.scrollFactor.x;
370 | daNote.mesh.scrollFactor.y = daNote.scrollFactor.y;
371 | daNote.alpha = noteData.alpha;
372 | daNote.mesh.alpha = daNote.alpha;
373 |
374 | var songSpeed = getCorrectScrollSpeed();
375 | var lane = noteData.lane;
376 |
377 | //makes the sustain match the center of the parent note when at weird angles
378 | var yOffsetThingy = (NoteMovement.arrowSizes[lane]/2);
379 |
380 | var thisNotePos = ModchartUtil.calculatePerspective(new Vector3D(noteData.x+(daNote.width/2)+ModchartUtil.getNoteOffsetX(daNote, instance), noteData.y+(NoteMovement.arrowSizes[noteData.lane]/2), noteData.z*0.001),
381 | ModchartUtil.defaultFOV*(Math.PI/180), -(daNote.width/2), yOffsetThingy-(NoteMovement.arrowSizes[noteData.lane]/2));
382 |
383 | var timeToNextSustain = ModchartUtil.getFakeCrochet()/4;
384 | if (noteData.noteDist < 0)
385 | timeToNextSustain *= -1; //weird shit that fixes upscroll lol
386 | // timeToNextSustain = -ModchartUtil.getFakeCrochet()/4; //weird shit that fixes upscroll lol
387 |
388 | #if (PSYCH && !(PSYCHVERSION >= "0.7"))
389 | var nextHalfNotePos = getSustainPoint(noteData, timeToNextSustain*0.5);
390 | var nextNotePos = getSustainPoint(noteData, timeToNextSustain);
391 | #else
392 | var nextHalfNotePos = ModchartUtil.getDownscroll(instance) ? getSustainPoint(noteData, timeToNextSustain*0.458) : getSustainPoint(noteData, timeToNextSustain*0.548);
393 | var nextNotePos = ModchartUtil.getDownscroll(instance) ? getSustainPoint(noteData, timeToNextSustain+2.2) : getSustainPoint(noteData, timeToNextSustain-2.2);
394 | #end
395 |
396 | var flipGraphic = false;
397 |
398 | // mod/bound to 360, add 360 for negative angles, mod again just in case
399 | var fixedAngY = ((noteData.incomingAngleY%360)+360)%360;
400 |
401 | var reverseClip = (fixedAngY > 90 && fixedAngY < 270);
402 |
403 | if (noteData.noteDist > 0) //downscroll
404 | {
405 | if (!ModchartUtil.getDownscroll(instance)) //fix reverse
406 | flipGraphic = true;
407 | }
408 | else
409 | {
410 | if (ModchartUtil.getDownscroll(instance))
411 | flipGraphic = true;
412 | }
413 | //render that shit
414 | daNote.mesh.constructVertices(noteData, thisNotePos, nextHalfNotePos, nextNotePos, flipGraphic, reverseClip);
415 |
416 | daNote.mesh.cameras = this.cameras;
417 | daNote.mesh.draw();
418 | }
419 |
420 | private function drawStuff(notePositions:Array)
421 | {
422 | for (noteData in notePositions)
423 | {
424 | if (noteData.isStrum) //draw strum
425 | drawStrum(noteData);
426 | else if (!notes.members[noteData.index].isSustainNote) //draw regular note
427 | drawNote(noteData);
428 | else{ //draw sustain
429 | #if LEATHER /*disable the funny sustains options for low-end pc lol*/if(utilities.Options.getData("optimizedModcharts")) drawNote(noteData) else #end drawSustainNote(noteData);
430 | }
431 |
432 | }
433 | }
434 |
435 | function getSustainPoint(noteData:NotePositionData, timeOffset:Float):NotePositionData
436 | {
437 | var daNote:Note = notes.members[noteData.index];
438 | var songSpeed:Float = getCorrectScrollSpeed();
439 | var lane:Int = noteData.lane;
440 | var pf:Int = noteData.playfieldIndex;
441 |
442 | var noteDist:Float = getNoteDist(noteData.index);
443 | var curPos:Float = getNoteCurPos(noteData.index, timeOffset);
444 |
445 | curPos = modifierTable.applyCurPosMods(lane, curPos, pf);
446 |
447 | if ((daNote.wasGoodHit || (daNote.prevNote.wasGoodHit)) && curPos >= 0)
448 | curPos = 0;
449 | noteDist = modifierTable.applyNoteDistMods(noteDist, lane, pf);
450 | var incomingAngle:Array = modifierTable.applyIncomingAngleMods(lane, curPos, pf);
451 | if (noteDist < 0)
452 | incomingAngle[0] += 180; //make it match for both scrolls
453 | //get the general note path for the next note
454 | NoteMovement.setNotePath(daNote, lane, songSpeed, curPos, noteDist, incomingAngle[0], incomingAngle[1]);
455 | //save the position data
456 | var noteData = createDataFromNote(noteData.index, pf, curPos, noteDist, incomingAngle);
457 | //add offsets to data with modifiers
458 | modifierTable.applyNoteMods(noteData, lane, curPos, pf);
459 | var yOffsetThingy = (NoteMovement.arrowSizes[lane]/2);
460 | var finalNotePos = ModchartUtil.calculatePerspective(new Vector3D(noteData.x+(daNote.width/2)+ModchartUtil.getNoteOffsetX(daNote, instance), noteData.y+(NoteMovement.arrowSizes[noteData.lane]/2), noteData.z*0.001),
461 | ModchartUtil.defaultFOV*(Math.PI/180), -(daNote.width/2), yOffsetThingy-(NoteMovement.arrowSizes[noteData.lane]/2));
462 |
463 | noteData.x = finalNotePos.x;
464 | noteData.y = finalNotePos.y;
465 | noteData.z = finalNotePos.z;
466 |
467 | return noteData;
468 | }
469 |
470 | public function getCorrectScrollSpeed()
471 | {
472 | if (inEditor)
473 | return PlayState.SONG.speed; //just use this while in editor so the instance shit works
474 | else
475 | return ModchartUtil.getScrollSpeed(playStateInstance);
476 | return 1.0;
477 | }
478 |
479 | public function createTween(Object:Dynamic, Values:Dynamic, Duration:Float, ?Options:TweenOptions):FlxTween
480 | {
481 | var tween:FlxTween = tweenManager.tween(Object, Values, Duration, Options);
482 | tween.manager = tweenManager;
483 | return tween;
484 | }
485 |
486 | public function createTweenNum(FromValue:Float, ToValue:Float, Duration:Float = 1, ?Options:TweenOptions, ?TweenFunction:Float->Void):FlxTween
487 | {
488 | var tween:FlxTween = tweenManager.num(FromValue, ToValue, Duration, Options, TweenFunction);
489 | tween.manager = tweenManager;
490 | return tween;
491 | }
492 |
493 | public function createBezierPathTween(Object:Dynamic, Values:Dynamic, Duration:Float, ?Options:TweenOptions):FlxTween
494 | {
495 | var tween:FlxTween = tweenManager.bezierPathTween(Object, Values, Duration, Options);
496 | tween.manager = tweenManager;
497 | return tween;
498 | }
499 |
500 | public function createBezierPathNumTween(Points:Array, Duration:Float, ?Options:TweenOptions, ?TweenFunction:Float->Void):FlxTween
501 | {
502 | var tween:FlxTween = tweenManager.bezierPathNumTween(Points, Duration, Options,TweenFunction);
503 | tween.manager = tweenManager;
504 | return tween;
505 | }
506 |
507 | override public function destroy()
508 | {
509 | if (modchart != null)
510 | {
511 | #if hscript
512 | for (customMod in modchart.customModifiers)
513 | {
514 | customMod.destroy(); //make sure the interps are dead
515 | }
516 | #end
517 | }
518 | super.destroy();
519 | }
520 |
521 | }
522 |
--------------------------------------------------------------------------------
/source/modcharting/SimpleQuaternion.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | import flixel.math.FlxAngle;
4 | import openfl.geom.Vector3D;
5 | import flixel.math.FlxMath;
6 |
7 | typedef Quaternion =
8 | {
9 | var x:Float;
10 | var y:Float;
11 | var z:Float;
12 | var w:Float;
13 | };
14 | //me whenthe
15 | class SimpleQuaternion
16 | {
17 | //no more gimbal lock fuck you
18 | public static function fromEuler(roll:Float, pitch:Float, yaw:Float) : Quaternion
19 | {
20 | //https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
21 | var cr = FlxMath.fastCos(roll * FlxAngle.TO_RAD);
22 | var sr = FlxMath.fastSin(roll * FlxAngle.TO_RAD);
23 | var cp = FlxMath.fastCos(pitch * FlxAngle.TO_RAD);
24 | var sp = FlxMath.fastSin(pitch * FlxAngle.TO_RAD);
25 | var cy = FlxMath.fastCos(yaw * FlxAngle.TO_RAD);
26 | var sy = FlxMath.fastSin(yaw * FlxAngle.TO_RAD);
27 |
28 | var q:Quaternion = {x: 0, y: 0, z: 0, w:0 };
29 | q.w = cr * cp * cy + sr * sp * sy;
30 | q.x = sr * cp * cy - cr * sp * sy;
31 | q.y = cr * sp * cy + sr * cp * sy;
32 | q.z = cr * cp * sy - sr * sp * cy;
33 | return q;
34 | }
35 | public static function transformVector(v:Vector3D, q:Quaternion) : Vector3D
36 | {
37 |
38 |
39 | return v;
40 | }
41 | public static function normalize(q:Quaternion) : Quaternion
42 | {
43 | var length = Math.sqrt(q.w*q.w + q.x*q.x + q.y*q.y + q.z*q.z);
44 | q.w = q.w / length;
45 | q.x = q.x / length;
46 | q.y = q.y / length;
47 | q.z = q.z / length;
48 |
49 | return q;
50 | }
51 | public static function conjugate(q:Quaternion) : Quaternion
52 | {
53 | q.y = -q.y;
54 | q.z = -q.z;
55 | q.w = -q.w;
56 | return q;
57 | }
58 | public static function multiply(q1:Quaternion, q2:Quaternion) : Quaternion
59 | {
60 | var x = q1.x * q2.x - q1.y * q2.y - q1.z * q2.z - q1.w * q2.w;
61 | var y = q1.x * q2.y + q1.y * q2.x + q1.z * q2.w - q1.w * q2.z;
62 | var z = q1.x * q2.z - q1.y * q2.w + q1.z * q2.x + q1.w * q2.y;
63 | var w = q1.x * q2.w + q1.y * q2.z - q1.z * q2.y + q1.w * q2.x;
64 |
65 | q1.x = x;
66 | q1.y = y;
67 | q1.z = z;
68 | q1.w = w;
69 |
70 | return q1;
71 | }
72 | }
--------------------------------------------------------------------------------
/source/modcharting/SustainStrip.hx:
--------------------------------------------------------------------------------
1 | package modcharting;
2 |
3 | import flixel.graphics.tile.FlxDrawTrianglesItem.DrawData;
4 | import openfl.geom.Vector3D;
5 | #if LEATHER
6 | import game.Note;
7 | #elseif (PSYCH && PSYCHVERSION >= "0.7")
8 | import objects.Note;
9 | #else
10 | import Note;
11 | #end
12 | import flixel.FlxStrip;
13 |
14 | class SustainStrip extends FlxStrip
15 | {
16 | private static final noteUV:Array = [
17 | 0,0, //top left
18 | 1,0, //top right
19 | 0,0.5, //half left
20 | 1,0.5, //half right
21 | 0,1, //bottom left
22 | 1,1, //bottom right
23 | ];
24 | private static final noteIndices:Array = [
25 | 0,1,2,1,3,2, 2,3,4,3,4,5
26 | //makes 4 triangles
27 | ];
28 |
29 | private var daNote:Note;
30 |
31 | override public function new(daNote:Note)
32 | {
33 | this.daNote = daNote;
34 | daNote.alpha = 1;
35 | super(0,0);
36 | loadGraphic(daNote.updateFramePixels());
37 | shader = daNote.shader;
38 | for (uv in noteUV)
39 | {
40 | uvtData.push(uv);
41 | vertices.push(0);
42 | }
43 | for (ind in noteIndices)
44 | indices.push(ind);
45 | }
46 |
47 | public function constructVertices(noteData:NotePositionData, thisNotePos:Vector3D, nextHalfNotePos:NotePositionData, nextNotePos:NotePositionData, flipGraphic:Bool, reverseClip:Bool)
48 | {
49 | var yOffset = -1; //fix small gaps
50 | if (reverseClip)
51 | yOffset *= -1;
52 |
53 | var verts:Array = [];
54 | if (flipGraphic)
55 | {
56 | verts.push(nextNotePos.x);
57 | verts.push(nextNotePos.y); //slight offset to fix small gaps
58 | verts.push(nextNotePos.x+(daNote.frameWidth*(1/-nextNotePos.z)*noteData.scaleX));
59 | verts.push(nextNotePos.y);
60 |
61 | verts.push(nextHalfNotePos.x);
62 | verts.push(nextHalfNotePos.y);
63 | verts.push(nextHalfNotePos.x+(daNote.frameWidth*(1/-nextHalfNotePos.z)*noteData.scaleX));
64 | verts.push(nextHalfNotePos.y);
65 |
66 | verts.push(thisNotePos.x);
67 | verts.push(thisNotePos.y);
68 | verts.push(thisNotePos.x+(daNote.frameWidth*(1/-thisNotePos.z)*nextNotePos.scaleX));
69 | verts.push(thisNotePos.y);
70 | }
71 | else
72 | {
73 | verts.push(thisNotePos.x);
74 | verts.push(thisNotePos.y); //fliped this with the down ones (last) to test if it bugs of it fixes itself
75 | verts.push(thisNotePos.x+(daNote.frameWidth*(1/-thisNotePos.z)*noteData.scaleX));
76 | verts.push(thisNotePos.y);
77 |
78 | verts.push(nextHalfNotePos.x);
79 | verts.push(nextHalfNotePos.y);
80 | verts.push(nextHalfNotePos.x+(daNote.frameWidth*(1/-nextHalfNotePos.z)*noteData.scaleX));
81 | verts.push(nextHalfNotePos.y);
82 |
83 | verts.push(nextNotePos.x);
84 | verts.push(nextNotePos.y); //slight offset to fix small gaps
85 | verts.push(nextNotePos.x+(daNote.frameWidth*(1/-nextNotePos.z)*nextNotePos.scaleX));
86 | verts.push(nextNotePos.y);
87 | }
88 | vertices = new DrawData(12, true, verts);
89 | }
90 | }
--------------------------------------------------------------------------------