--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
--- /dev/null
+= CLONEMON
+
+Clonemon is a game I am working on that uses my custom game engine called the
+nyquist2DEngine. The source code for the game engine is not included in this
+repository.
+
+== Controls
+
+[%header, cols="1,1"]
+|===
+| key / keycombo | control
+
+| enter/j | select
+| cntrl + ~ | enter terminal
+| w | move up
+| a | move left
+| s | move down
+| d | move right
+| k | select up
+| h | select left
+| j | select down
+| l | select right
+| esc | pause
+|===
+
+== Terminal commands
+
+[%header, cols="1,1"]
+|===
+| command | action
+
+| c.bag() | change to bag global state
+| c.world() | chanage to world global state
+| c.enter_text() | chanage to enter text global state
+| c.start() | chanage to start global state
+| c.choice_select() | chanage to choice select global state
+| c.loadsave() | chanage to loadsave global state
+| c.party() | chanage to party gobal state
+| c.battle() | chanage to party gobal state
+| c.setState() | change to a substate ex. setState(states.battle.moveSelect)
+| lua <command> | enter custom lua
+|===
+
+== Terminal substates
+
+Every substate only works while running in the correct global state. For
+example any `states.battle` state only works in the battle global state.
+
+[%header, cols="1,4"]
+|===
+| substate | action
+
+| states.battle.moveSelect | pick from your clonemons available moves
+| states.battle.doSelect | decide what your clonemon will do in battle
+| states.battle.enterBattle | starts the battle intro
+| states.party.doWhat | decide what you want to do with choosen clonemon
+| states.party.switch | switch clonemon to a different party slot
+|===
+
+
+== Installation
+
+Put the binaries create from building the nyquist2DEnine engine or mapeditor in
+the root directory. The "*.so" or ".dll" files created from building the
+nyquist2DEngine extensions in the root of the extensions folder.
+
+
+== Running
+run these commands to initialize the game
+
+----
+./scripts/init
+./scripts/sourceme
+----
+
+you can do
+
+----
+./n2de_dev
+----
+
+or
+
+----
+./n2de
+----
+
+run run the game
--- /dev/null
+#!/usr/bin/env bash
+HOSTNAME=nyquistdev.net
+DOCINFODIR=/usr/local/share/readme-to-html
--- /dev/null
+= Map Chunk loader
+:docinfo: shared
+:toc: left
+:source-highlighter: pygments
+:incons: font
+:stem:
+
+each outdoor map should be loaded in chunks. The chunks should have a top,
+right, left or bottom attribute that points to another map. The width and height
+should be a square of 480 by 320, that's double the screen size.
+
+map.x > 0::
+ load left map
+
+-map_pos.x > screen width::
+ load right map
+
+map.y > 0::
+ load top map
+
+-map_pos.y > screen height::
+ load bottom map
+
+In order to test this I can make maps that are one solid color but all different
+colors and see if the get loaded
+
+only load the collision for the map you are currently in
+
+once you are within a map, you should load the chunks for that map. make sure
+those chunks include visability for the chunk you were previously in, if you
+would be able to see it
+
+== Map Generation
+
+An array of map ids is called a `map_spec`. Each `map_spec` has specific map ids
+to met a specific criteria for the world. A random map id from a `map_spec` is
+chosen. This id along with position of the next map (`next_pos`) is stored into
+the `maps` array. `next_pos` could have a position above, to the right, below or
+to the left of the current map as long as a map or border does not exist in that
+position. If there is a map or border on the top, left, bottom and right then
+`next_pos` will be nil and the map will be stored in the `blocked` array. The
+`maps` array has elements stored at the index of the position of the map. The
+first map created has a position of zero, if it is not the first map than the
+position is the position of `next_pos` of the previous element in `maps` as long
+as it is not nil, if it is a different position is chosen that is not in the
+`maps` or `blocked` array. This is done a number of times for each `map_spec`.
+The number of times this is done is specified by the `map_spec`'s limit.
+
+
+== Map Position
+The world is an 4x4 grid. Even though this is two demensional each map in the
+world is stored in a one demensional array like so:
+
+[ditaa]
+----
++---+---+---+---+
+|13 |14 |15 |16 |
++---+---+---+---+
+| 9 |10 |11 |12 |
++---+---+---+---+
+| 5 | 6 | 7 | 8 |
++---+---+---+---+
+| 1 | 2 | 3 | 4 |
++---+---+---+---+
+----
+
+So you can find the top element by doing `n + 8`, the bottom element by doing
+`n - 8`, right element by doing `n + 1` and left element by doing `n - 1`
+
+[ditaa]
+----
+ n + 8
+ +---+
+n - 1 | n | n + 1
+ +---+
+ n - 8
+----
+
+kindof...
+
+This doesn't really work because of the borders of the 8x4 grid. If x was 9 then
+according to this logic the element to the left would be (x - 1), and that is
+incorrect. So you can use a function like this to check borders
+
+[source lua]
+----
+function getSurronding(n, grid)
+ local x = ((n - 1) % grid) + 1
+ local y = math.floor((n - 1) / grid) + 1
+
+ return {
+ left = x > 1 and n - 1 or nil,
+ right = x < grid and n + 1 or nil,
+ top = n + grid <= grid * grid and n + grid or nil,
+ bottom = n - grid > 0 and n - grid or nil,
+ }
+end
+----
--- /dev/null
+== Run in Linux without steam
+
+----
+wine n2de.exe
+----
--- /dev/null
+== TODO
+
+- [ ] Make private section of ui_mt.lua
+
+ * you can create getter and setter functions to aid with this
+
+ * use const keyword `local a <const> = 12` (need to upgrade to lua5.4)
+
+ * make an https://stackoverflow.com/questions/46977997/lua-metatables-first-parameter-in-index-function#51693548[index function] instead of a table and make tab be the local const
+ variables instead of the _ui.lua_ find
+
+
+- [ ] Make it so you don't need an if else statements when changing states
+
+- [ ] Change option select so it is initialized in the start function
+
+- [x] Set Controlls from database instead
+
+- [ ] Make Party box ui
+
+- [ ] Finish setting up ./resources/images/spritesheet_indoors_1.png
+
+- [ ] Create a better way to change maps
+
+- [ ] Create a path follow for characters. This will automate characters to move
+ along a certain path
+
+- [ ] make map load chunks as you get close to the edge of the map
+
+- [ ] make collision work bettween the current map and the map you are about to
+ enter
+
+- [ ] Make `rng` in layout an array of objects
+
+- [ ] Create a save state for the map layout, maybe in __./resources/data/saves_
+
+== terminal
+
+- [ ] Add command to see hitboxes
+
+- [ ] Add command for no cliping
+
--- /dev/null
+local libaudio = require("extensions.libaudio")
+return libaudio
--- /dev/null
+local config = {}
+
+local db_config = Ex.Database.getAll("config")
+
+-- this is the configuration for what is in the database
+config.db = {
+ fullscreen = true;
+ controller = "none";
+ resolution_scale = 5;
+ speed = 4;
+}
+
+-- this is the configuration for what is active and may not be in the database
+-- yet
+config.fullscreen = true
+config.controller = "none"
+config.resolution_scale = 5
+config.speed = 4
+
+if #db_config == 0 then
+ print("creating settings config")
+ if nyq.getGamepads() and (nyq.getGamepads()[1]) then
+ config.controller = nyq.getGamepads()[1]
+ config.db.controller = config.controller
+ end
+ Ex.Database.insert("config", {
+ controller = config.controller,
+ fullscreen = config.fullscreen and 1 or 0,
+ resolution_scale = config.resolution_scale,
+ speed = config.speed,
+ })
+else
+ for k1, v1 in pairs(db_config) do
+ if k1 == 1 then
+ for k2, v2 in pairs(v1) do
+ if k2 == "fullscreen" then
+ config[k2] = v2 > 0
+ config.db[k2] = config[k2]
+ elseif k2 == "resolution_scale" then
+ config[k2] = math.floor(v2)
+ config.db[k2] = config[k2]
+ elseif k2 == "controller" then
+ if nyq.getGamepads() and (not #nyq.getGamepads()[1]) then
+ config.controller = "none"
+ else
+ config[k2] = v2
+ end
+ config.db[k2] = v2
+ else
+ config[k2] = v2
+ config.db[k2] = v2
+ end
+ end
+ end
+ end
+end
+
+-- config.mappings = {}
+config.mappings = require("extensions.config.mappings")
+local db_gamepad_mappings = Ex.Database.getAll("gamepad_mappings")
+
+if #db_gamepad_mappings == 0 then
+
+ -- database key value pairs NEED to be in the correct order thats why I cannot itterate
+ local mappings = config.mappings.gamepad
+ Ex.Database.insert("gamepad_mappings", {
+ move_north = mappings.move_north.key,
+ move_east = mappings.move_east.key,
+ move_south = mappings.move_south.key,
+ move_west = mappings.move_west.key,
+ move_up = mappings.move_up.key,
+ move_right = mappings.move_right.key,
+ move_down = mappings.move_down.key,
+ move_left = mappings.move_left.key,
+ _select = mappings.select.key,
+ back = mappings.back.key,
+ pause = mappings.pause.key,
+ hotkey = mappings.hotkey.key,
+ })
+else
+ for k, v in pairs(db_gamepad_mappings[1]) do
+ if k == "_select" then
+ k = "select"
+ end
+ config.mappings.gamepad[k].key = v
+ end
+end
+
+local db_keyboard_mappings = Ex.Database.getAll("keyboard_mappings")
+if #db_keyboard_mappings == 0 then
+
+ -- database key value pairs NEED to be in the correct order thats why I cannot itterate
+ local mappings = config.mappings.keyboard
+ Ex.Database.insert("keyboard_mappings", {
+ move_north = mappings.move_north.key,
+ move_east = mappings.move_east.key,
+ move_south = mappings.move_south.key,
+ move_west = mappings.move_west.key,
+ move_up = mappings.move_up.key,
+ move_right = mappings.move_right.key,
+ move_down = mappings.move_down.key,
+ move_left = mappings.move_left.key,
+ _select = mappings.select.key,
+ back = mappings.back.key,
+ pause = mappings.pause.key,
+ hotkey = mappings.hotkey.key,
+ })
+else
+ for k, v in pairs(db_keyboard_mappings[1]) do
+ if k == "_select" then
+ k = "select"
+ end
+ config.mappings.keyboard[k].key = v
+ end
+end
+
+
+return config
--- /dev/null
+return {
+ move_north = {
+ key = "dpup";
+ trigger = false;
+ keyrepeat = false;
+ },
+ move_east = {
+ key = "dpright";
+ trigger = false;
+ keyrepeat = false;
+ },
+ move_south = {
+ key = "dpdown";
+ trigger = false;
+ keyrepeat = false;
+ },
+ move_west = {
+ key = "dpleft";
+ trigger = false;
+ keyrepeat = false;
+ },
+ move_up = {
+ key = "dpup";
+ trigger = true;
+ keyrepeat = false;
+ },
+ move_right = {
+ key = "dpright";
+ trigger = true;
+ keyrepeat = false;
+ },
+ move_down = {
+ key = "dpdown";
+ trigger = true;
+ keyrepeat = false;
+ },
+ move_left = {
+ key = "dpleft";
+ trigger = true;
+ keyrepeat = false;
+ },
+ select = {
+ key = "a";
+ trigger = false;
+ keyrepeat = false;
+ },
+ back = {
+ key = "b";
+ trigger = true;
+ keyrepeat = false;
+ },
+ pause = {
+ key = "start";
+ trigger = true;
+ keyrepeat = false;
+ },
+ hotkey = {
+ key = "x";
+ trigger = true;
+ keyrepeat = false;
+ },
+}
--- /dev/null
+return {
+ move_north = {
+ key = "W";
+ trigger = false;
+ keyrepeat = true;
+ },
+ move_east = {
+ key = "D";
+ trigger = false;
+ keyrepeat = true;
+ },
+ move_south = {
+ key = "S";
+ trigger = false;
+ keyrepeat = true;
+ },
+ move_west = {
+ key = "A";
+ trigger = false;
+ keyrepeat = true;
+ },
+ move_up = {
+ key = "Up";
+ trigger = true;
+ keyrepeat = true;
+ },
+ move_right = {
+ key = "Right";
+ trigger = true;
+ keyrepeat = true;
+ },
+ move_down = {
+ key = "Down";
+ trigger = true;
+ keyrepeat = true;
+ },
+ move_left = {
+ key = "Left";
+ trigger = true;
+ keyrepeat = true;
+ },
+ select = {
+ key = "Return";
+ trigger = true;
+ keyrepeat = false;
+ },
+ pause = {
+ key = "Escape";
+ trigger = true;
+ keyrepeat = false;
+ },
+ back = {
+ key = "Backspace";
+ trigger = true;
+ keyrepeat = false;
+ },
+ hotkey = {
+ key = "X";
+ trigger = true;
+ keyrepeat = false;
+ },
+}
--- /dev/null
+return {
+ gamepad = require("extensions.config.mappings.default_gamepad");
+ keyboard = require("extensions.config.mappings.default_keyboard");
+}
--- /dev/null
+local libdatabase = require("extensions.libdatabase")
+libdatabase.schema = require("extensions.database.schema")
+
+libdatabase.init("test.db", libdatabase.schema)
+World = {
+ clonemon_types = libdatabase.getAll("clonemon_types"),
+ clonemon = libdatabase.getAll("clonemon")
+}
+return libdatabase
--- /dev/null
+return {
+ biomes = {
+ name = DB_TEXT_UNIQUE;
+ map_id = DB_INTEGER_UNIQUE;
+ effects = DB_TEXT_UNIQUE;
+ },
+ clonemon_types = {
+ name = DB_TEXT_UNIQUE;
+ ability = DB_TEXT;
+ base_attack = DB_INTEGER;
+ base_hp = DB_INTEGER;
+ base_speed = DB_INTEGER;
+ base_defense = DB_INTEGER;
+ base_special_defense = DB_INTEGER;
+ base_special_attack = DB_INTEGER;
+ image = DB_TEXT;
+ },
+ move_types = {
+ move_id = "moves";
+ name = DB_TEXT_UNIQUE;
+ base_power = DB_INTEGER;
+ base_accuracy = DB_INTEGER;
+ base_pp = DB_INTEGER;
+ base_speed = DB_INTEGER;
+ status_effect = DB_TEXT;
+ image = DB_TEXT;
+ },
+ moves = {
+ move_type_id = "move_types";
+ pp = DB_INTEGER;
+ power = DB_INTEGER;
+ accuracy = DB_INTEGER;
+ speed = DB_INTEGER;
+ },
+ move_types_compare = {
+ move_types = "move_types";
+ weak_id = "move_types";
+ strong_id = "move_types";
+ resistant_id = "move_types";
+ },
+ clonemon_biomes = {
+ clonemon_id = "clonemon",
+ biome_id = "biomes"
+ },
+ clonemon_moves = {
+ clonemon_id = "clonemon";
+ move_id = "moves"
+ },
+ clonemon = {
+ type_id = "clonemon_types";
+ name = DB_TEXT;
+ gender = DB_INTEGER;
+ level = DB_INTEGER;
+ attack = DB_INTEGER;
+ max_hp = DB_INTEGER;
+ remaining_hp = DB_INTEGER;
+ speed = DB_INTEGER;
+ defense = DB_INTEGER;
+ accuracy = DB_INTEGER;
+ special_defense = DB_INTEGER;
+ special_attack = DB_INTEGER;
+ box_number = DB_INTEGER;
+ box_position = DB_INTEGER;
+ spritesheet = DB_TEXT_UNIQUE;
+ },
+ people = {
+ age = DB_INTEGER;
+ name = DB_TEXT;
+ level = DB_INTEGER;
+ spritesheet = DB_TEXT;
+ },
+ clonemon_party = {
+ person_id = "people";
+ clonemon = "clonemon";
+ },
+ players = {
+ uuid = DB_TEXT_UNIQUE;
+ person_id = "people";
+ },
+ config = {
+ controller = DB_TEXT;
+ fullscreen = DB_INTEGER;
+ resolution_scale = DB_INTEGER;
+ speed = DB_INTEGER;
+ },
+ gamepad_mappings = {
+ move_north = DB_TEXT;
+ move_east = DB_TEXT;
+ move_south = DB_TEXT;
+ move_west = DB_TEXT;
+ move_up = DB_TEXT;
+ move_right = DB_TEXT;
+ move_down = DB_TEXT;
+ move_left = DB_TEXT;
+ _select = DB_TEXT;
+ back = DB_TEXT;
+ pause = DB_TEXT;
+ hotkey = DB_TEXT;
+
+ },
+ keyboard_mappings = {
+ move_north = DB_TEXT;
+ move_east = DB_TEXT;
+ move_south = DB_TEXT;
+ move_west = DB_TEXT;
+ move_up = DB_TEXT;
+ move_right = DB_TEXT;
+ move_down = DB_TEXT;
+ move_left = DB_TEXT;
+ _select = DB_TEXT;
+ back = DB_TEXT;
+ pause = DB_TEXT;
+ hotkey = DB_TEXT;
+ }
+}
--- /dev/null
+local libimages = require("extensions.libimages")
+return libimages
--- /dev/null
+Ex = {}
+Ex.Database = require("extensions.database")
+Ex.Audio = require("extensions.audio")
+Ex.Sprites = require("extensions.sprites")
+Ex.Loops = require("extensions.loops")
+Ex.Images = require("extensions.images")
+Ex.Text = require("extensions.text")
+if PRODUCTION then
+ terminal = { commands = require("extensions.terminal.commands") }
+else
+ Ex.Terminal = require("extensions.terminal")
+end
+Ex.Config = require("extensions.config") -- must be required last
--- /dev/null
+local libloops = require("extensions.libloops")
+return libloops
--- /dev/null
+-- TODO
+-- make getter and setter functions
+--
+local ui_mt = {}
+ui_mt.scale = 1
+ui_mt.window_size = {w = 0, h = 0}
+ui_mt.background = {
+ position = {x = 0, y = 0},
+ size = {w = 0, h = 0},
+ images = {},
+}
+ui_mt.font_size = nil
+ui_mt.spritesheet = nil
+ui_mt.lines = {}
+
+local menu_items_id = nil
+local background_image = nil
+local select_options = nil
+local select_max = nil
+local option_rect_id = nil
+local spritesheet_id = 0
+local ttf_file = nil
+local sprite_ids = {}
+local image_ids = {}
+local crops = {}
+local animation = {}
+local text = {}
+local notify = {
+ isNotifying = false,
+ start = 0,
+ type = "change",
+ str = "hey",
+ colors = {
+ change = {
+ fg = {r = 255, g = 255, b = 255, a = 255},
+ bg = {r = 0, g = 0, b = 0, a = 255}
+ },
+ warning = {
+ fg = {r = 255, g = 0, b = 0, a = 255},
+ bg = {r = 0, g = 0, b = 0, a = 255}
+ },
+ fg = {r = 255, g = 255, b = 255, a = 255},
+ bg = {r = 0, g = 0, b = 0, a = 255}
+ }
+}
+local optionSelect = {
+ options = nil
+}
+
+function ui_mt:setSize(size)
+ local s = {
+ w = size.w * self.scale,
+ h = size.h * self.scale
+ }
+ return s
+end
+
+function ui_mt:setPosition(pos)
+ local p = {
+ x = pos.x * self.scale,
+ y = pos.y * self.scale,
+ }
+ return p
+end
+
+function ui_mt:scaleRect(rect)
+local r = {
+ x = rect.x * self.scale,
+ y = rect.y * self.scale,
+ w = rect.w * self.scale,
+ h = rect.h * self.scale,
+ }
+ return r
+end
+
+function ui_mt:addCrop(name, crop, size, spritesheet)
+ if not crops[name] then
+ crops[name] = {}
+ end
+ crops[name].crop = crop
+ crops[name].size = size
+ if spritesheet then
+ Ex.Sprites.addCrops(spritesheet, name, 0, {crops[name].crop})
+ else
+ Ex.Sprites.addCrops(spritesheet_id, name, 0, {crops[name].crop})
+ end
+end
+
+function ui_mt:addAnimation(name, id, crops, size)
+ if (not animation[name]) then
+ animation[name] = {}
+ end
+ if (not animation[name]["crops"]) then
+ animation[name]["crops"] = {}
+ end
+ if (not animation[name]["crops"][id]) and crops then
+ animation[name]["crops"][id] = crops
+ end
+ Ex.Sprites.addCrops(spritesheet_id, id, 1, animation[name]["crops"][id])
+ animation[name].size = size
+end
+
+function ui_mt:updateAnimation(name, id, speed, pos)
+ local s = self:setSize(animation[name].size)
+ local s = self:setSize(animation[name].size)
+ local p = self:setPosition(pos)
+ animation[name].frame_number =
+ Ex.Sprites.animate(spritesheet_id, id, speed, p, s)
+end
+
+function ui_mt:updateCrop(name, pos)
+ local s = self:setSize(crops[name].size)
+ local p = self:setPosition(pos)
+ crops[name].position = pos
+ Ex.Sprites.updateCrop(spritesheet_id, name, 1, p, {size = s})
+end
+
+function ui_mt:updateCrop2(name, id, pos)
+ local s = self:setSize(crops[name].size)
+ local p = {
+ x = pos.x,
+ y = pos.y
+ }
+ crops[name].frame_number =
+ Ex.Sprites.updateCrop(spritesheet_id, id, 1, p, {size = s})
+end
+
+function ui_mt:addBackgroundImage(name, path)
+ self.background.images[name] = Ex.Images.create(path, 0)
+ table.insert(image_ids, self.background.images[name])
+end
+
+function ui_mt:setBackgroundImage(image)
+ if self.background.images[image] then
+ background_image = self.background.images[image]
+ return true
+ end
+
+ return false
+end
+
+function ui_mt:updateBackground()
+ local s = self:setSize(self.background.size)
+ local p = self:setPosition(self.background.position)
+ Ex.Images.update(background_image, p, s)
+end
+
+function ui_mt:setFont(file, size)
+ ttf_file = file
+ self.font_size = size
+end
+
+function ui_mt:addText(name, id, string, zIndex, fg_color, bg_color)
+ if not text[name] then
+ text[name] = {}
+ end
+
+ text[name].string = string
+
+ if not text[name][id] then
+ text[name][id] = Ex.Text.create(
+ ttf_file,
+ self.font_size * self.scale,
+ text[name].string,
+ zIndex,
+ fg_color,
+ bg_color
+ )
+ else
+ Ex.Text.change(
+ text[name][id],
+ text[name].string,
+ fg_color,
+ bg_color
+ )
+ end
+ table.insert(self._free_me, {name, id})
+end
+
+function ui_mt:clearText(name, id)
+ if not name then return end
+ text[name][id] = nil
+end
+
+function ui_mt:clearText2(o, id)
+ if not o then return end
+ o[id] = nil
+end
+
+function ui_mt:addText2(o, id, string, zIndex, fg_color, bg_color)
+ if not o[id] then
+ o[id] = Ex.Text.create(
+ ttf_file,
+ self.font_size * self.scale,
+ string,
+ zIndex,
+ fg_color,
+ bg_color
+ )
+ else
+ Ex.Text.change(
+ o[id],
+ string,
+ fg_color,
+ bg_color
+ )
+ end
+ table.insert(self._free_me, {o, id})
+end
+
+function ui_mt:free()
+ for _, v in pairs(self._free_me) do
+ if type(v[1]) == "string" then
+ text[ v[1] ][ v[2] ] = nil
+ elseif type(v[1]) == "table" then
+ -- k[v] = nil
+ v[1][ v[2] ] = nil
+ end
+ end
+
+ Ex.Text.clear()
+
+ if self.freeCallback then
+ self.freeCallback()
+ end
+
+ Ex.Sprites.quit()
+ Ex.Images.free()
+ nyq.world.free(0)
+ nyq.rects.free()
+
+end
+
+function ui_mt:textChange(name, id, str, forground_color, background_color)
+ Ex.Text.change(
+ text[name][id],
+ str,
+ forground_color,
+ background_color
+ )
+end
+
+function ui_mt:textChange2(o, id, str, forground_color, background_color)
+ Ex.Text.change(
+ o[id],
+ str,
+ forground_color,
+ background_color
+ )
+end
+
+function ui_mt:updateText2(o, id, position, offsets)
+ if (not o) then return end
+ if (not o[id]) then return end
+
+ if position.x == "center" then
+ local size = ui:getTextSize(name, id)
+ position.x = (self.window_size.w / 2) - (size.w / 2)
+
+ elseif position.x == "right" then
+ local size = ui:getTextSize(name, id)
+ position.x = self.window_size.w - size.w
+ end
+
+ if position.y == "bottom" then
+ position.y = self.window_size.h - self.font_size
+ end
+
+ if offsets then
+ if (offsets.x) then
+ position.x = position.x + offsets.x
+ end
+ if (offsets.y) then
+ position.y = position.y + offsets.y
+ end
+ end
+
+ local p = self:setPosition(position)
+ Ex.Text.update(o[id], p)
+end
+
+function ui_mt:updateText(name, id, position, offsets)
+ if (not text[name]) then return end
+ if (not text[name][id]) then return end
+
+ if position.x == "center" then
+ local size = ui:getTextSize(name, id)
+ position.x = (self.window_size.w / 2) - (size.w / 2)
+
+ elseif position.x == "right" then
+ local size = ui:getTextSize(name, id)
+ position.x = self.window_size.w - size.w
+ end
+
+ if position.y == "center" then
+ -- TODO
+ -- finish this if :p
+ elseif position.y == "bottom" then
+ position.y = self.window_size.h - self.font_size
+ end
+
+ if offsets then
+ if (offsets.x) then
+ position.x = position.x + offsets.x
+ end
+ if (offsets.y) then
+ position.y = position.y + offsets.y
+ end
+ end
+
+ local p = ui:setPosition(position)
+
+ if (text[name].string) then
+ Ex.Text.update(text[name][id], p)
+ end
+end
+
+function ui_mt:getTextSize(name, id)
+ if (not text[name]) then return end
+ if (not text[name][id]) then return end
+ local size = Ex.Text.getSize(text[name][id])
+ return {
+ w = size.w / self.scale,
+ h = size.h / self.scale,
+ }
+end
+
+function ui_mt:getTextSize2(o, id)
+ if (not o) then return end
+ if (not o[id]) then return end
+ local size = Ex.Text.getSize(o[id])
+ return {
+ w = size.w / self.scale,
+ h = size.h / self.scale,
+ }
+end
+
+function ui_mt:newSprite(file)
+ local id = Ex.Sprites.new(file)
+ table.insert(sprite_ids, id)
+ return id
+end
+
+function ui_mt:spriteAddCrops(id, id2, zIndex, frames)
+ Ex.Sprites.addCrops(id, id2, zIndex, frames)
+end
+
+function ui_mt:spriteUpdateCrop(id, id2, idx, pos, scale)
+ local p = self:setPosition(pos)
+ if scale then
+ local s = self:setSize(scale)
+ Ex.Sprites.updateCrop(id, id2, idx, p, {size = s})
+ else
+ Ex.Sprites.updateCrop(id, id2, idx, p, {
+ scale = {
+ w = self.scale,
+ h = self.scale
+ }
+ })
+ end
+end
+
+function ui_mt:imageCreate(file, zIndex)
+ local id = 0
+ id = Ex.Images.create(file, zIndex)
+ table.insert(image_ids, id)
+ return id
+end
+
+function ui_mt:imageUpdate(id, pos, size)
+ local p = self:setPosition(pos)
+ local s = self:setSize(size)
+ Ex.Images.update(id, p, s)
+end
+
+function ui_mt:_init(spritesheet, window_size, file, font_size, options,
+ callback)
+
+ if spritesheet then
+ self.spritesheet = spritesheet
+ end
+
+ if options then
+ if options.scale then
+ self.scale = options.scale
+ end
+ if options.pos then
+ self.pos = options.pos
+ end
+ if options.background_position then
+ self.background.position = options.background_position
+ end
+ end
+
+
+ self:setFont(file, font_size)
+ self.isChangeingInput = false
+ local window_size = {w = 240, h = 160}
+ self.window_size = window_size
+ self.scaled_window_size = {w = window_size.w * self.scale,
+ h = window_size.h * self.scale}
+ self.background.size = window_size
+ self._free_me = {}
+ local p = self:setPosition(self.background.position)
+ callback()
+end
+
+function ui_mt:createRect(color, fill, zIndex)
+ return nyq.rects.create(color, fill, zIndex)
+end
+
+function ui_mt:rectUpdate(id, pos, size)
+ local p = self:setPosition(pos)
+ local s = self:setSize(size)
+ nyq.rects.update(id, p, s)
+end
+
+function ui_mt:start()
+ self:addText("notification", "change", "nothing", 5,
+ notify.colors.change.fg,
+ notify.colors.change.bg
+ )
+ self:addText("notification", "warning", "nothing", 5,
+ notify.colors.warning.fg,
+ notify.colors.warning.bg
+ )
+
+ if self.spritesheet then
+ spritesheet_id = Ex.Sprites.new(self.spritesheet)
+ end
+
+ for i = 1, 6 do
+ self:addText("options", i , "yes", 5,
+ {r = 0, g = 0, b = 0, a = 255},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+ end
+ option_rect_id = self:createRect({r = 225, g = 255, b = 255, a = 200}, true, 4)
+ menu_items_id = self:newSprite("menu_items.png")
+ self:spriteAddCrops(menu_items_id, "selection arrow", 6, {
+ {
+ x = 7,
+ y = 0,
+ w = 7,
+ h = 7
+ }
+ })
+ self:spriteAddCrops(menu_items_id, "transparent_arrow_left", 6, {
+ {
+ x = 14,
+ y = 0,
+ w = 7,
+ h = 7
+ }
+ })
+ self:spriteAddCrops(menu_items_id, "transparent_arrow_right", 6, {
+ {
+ x = 21,
+ y = 0,
+ w = 7,
+ h = 7
+ }
+ })
+ self:spriteAddCrops(menu_items_id, "up arrow", 0, {
+ {
+ x = 28,
+ y = 0,
+ w = 15,
+ h = 15
+ }
+ })
+ self:spriteAddCrops(menu_items_id, "down arrow", 0, {
+ {
+ x = 43,
+ y = 0,
+ w = 15,
+ h = 15
+ }
+ })
+ if self.startCallback then
+ self:startCallback()
+ end
+end
+
+function ui_mt:linesCreate(name, count, fg_color, bg_color)
+ self.lines[name] = {}
+ self.lines[name].line_count = count
+ self.lines[name].line_ids = {}
+ self.lines[name].page_idx = 0
+ self.lines[name].pages = 0
+ self.lines[name].fg_color = fg_color
+ self.lines[name].bg_color = bg_color
+
+ for i = 1, count do
+ self:addText2(
+ self.lines[name].line_ids,
+ i,
+ "lines", -- cannot leave blank
+ 5,
+ self.lines[name].fg_color,
+ self.lines[name].bg_color
+ )
+ end
+end
+
+function ui_mt:optionSelectInit(options)
+ optionSelect.options = options
+ selection_max = #optionSelect.options
+ select_options = {}
+
+ local rev = table.Reverse(optionSelect.options)
+
+ for i, option in pairs(rev) do
+ self:textChange("options", option.id, option.text,
+ {r = 0, g = 0, b = 0, a = 255},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+ end
+ return selection_max
+end
+
+function ui_mt:optionSelectUpdate(start_pos, selected)
+ local height = 1
+ local font_offset = self.font_size + 1
+ local max_width = {
+ len = 0,
+ id = 0
+ }
+
+ for i, option in pairs(optionSelect.options) do
+ select_options[option] = i;
+ local len = string.len(option)
+ if len > max_width.len then
+ max_width.len = len
+ max_width.id = i
+ end
+ end
+
+ local size = self:getTextSize("options", max_width.id)
+ local rect_pos = {x = start_pos.x - size.w - 12, y = start_pos.y + 8}
+ local rev = table.Reverse(optionSelect.options)
+
+ for i, option in pairs(rev) do
+ local y_offset = (i - 1) * font_offset
+ height = height + font_offset
+ rect_pos.y = rect_pos.y - font_offset
+ self:updateText("options", option.id, {
+ -- x = 238 - size.w,
+ x = start_pos.x- size.w,
+ y = start_pos.y - y_offset
+ })
+ end
+
+ self:rectUpdate(option_rect_id,
+ rect_pos,
+ {
+ w = size.w + 14,
+ h = height + 2
+ })
+ self:spriteUpdateCrop(menu_items_id, "selection arrow", 1, {
+ x = start_pos.x - size.w - 10,
+ y = (start_pos.y + 3 + font_offset - height) +
+ (font_offset * (selected - 1))
+ })
+end
+
+function ui_mt:getSelectOptions()
+ return select_options
+end
+
+function ui_mt:updateMenuItem(id2, idx, pos, scale)
+ self:spriteUpdateCrop(menu_items_id, id2, idx, pos, scale)
+end
+
+function ui_mt:linesDraw(name, text, len, position)
+ local lines = string.WordWrap(text, len)
+ self.lines[name].pages = math.ceil(#lines / self.lines[name].line_count)
+ local max = #lines
+ if max > self.lines[name].line_count then max = self.lines[name].line_count end
+ for i = 1, max do
+ if not self.lines[i + (self.lines[name].page_idx * self.lines[name].line_count)] then
+ return true
+ end
+ local y = position.y + ((i - 1) * (self.font_size + 1))
+ self:textChange2(self.lines[name].line_ids, i,
+ self.lines[i + (self.lines[name].page_idx *
+ self.lines[name].line_count)], self.lines[name].fg_color,
+ self.lines[name].bg_color)
+
+ self:updateText2(self.lines[name].line_ids, i, {
+ x = position.x,
+ y = y
+ })
+ end
+ return false
+end
+
+function ui_mt:notifySet(type, str)
+ self:textChange("notification", type, str, notify.colors[type].fg,
+ notify.colors[type].bg)
+ notify.start = nyq.getTicks()
+ notify.str = str
+ notify.type = type
+ notify.fg = Copy.shallow_copy(notify.colors[type].fg)
+ notify.bg = Copy.shallow_copy(notify.colors[type].bg)
+ self.isNotifying = true
+
+end
+
+function ui_mt:notifyUpdate()
+ if not self.isNotifying then return end
+
+ if (nyq.getTicks() - notify.start >= 3000) then
+ notify.isNotifying = false
+ return
+ end
+
+ local size = assert(self:getTextSize("notification", notify.type))
+ if notify.bg.a >= 0 then
+ notify.bg.a = notify.bg.a - 1.3
+ end
+ if notify.fg.a >= 0 then
+ notify.fg.a = notify.fg.a - 1.3
+ end
+ self:textChange("notification", notify.type, notify.str,
+ notify.fg, notify.bg)
+
+ local pos = {
+ x = "right",
+ y = "bottom"
+ }
+
+ self:updateText("notification", notify.type, pos, {x = -2, y = -2})
+end
+
+function assign(name, t1)
+ local mt <const> = Copy.deepcopy(ui_mt)
+ for k,v in pairs(t1) do
+ if mt[k] then
+ print(string.format("%s ui: '%s' is already assigned", name, k))
+ os.exit(1)
+ end
+ end
+ return setmetatable(t1, {
+ __index = function(table, key)
+ return mt[key]
+ end,
+ __newindex = function(table, key, value)
+ if mt[key] then
+ print(string.format("%s ui: '%s' is private", name, key))
+ os.exit(2)
+ end
+ mt[key] = value
+ end
+ }), mt
+end
+
+return assign
--- /dev/null
+local libsprites = require("extensions.libsprites")
+return libsprites
--- /dev/null
+return {
+ setState = function(s)
+ local found = false
+ for k1, v1 in pairs(states) do
+ for k2, v2 in pairs(v1) do
+ if states[k1][k2] == state then
+ state = states[k1][s]
+ found = true
+ end
+ end
+ end
+ if s or found then
+ Ex.Terminal.message("setting state")
+ else
+ Ex.Terminal.error("could not set state")
+ end
+ end,
+ start = function()
+ states.start.main:reset()
+ -- temps.state = states.start.main
+ state = states.start.main
+ temps.ui = uis.start
+ -- nyq.audio.play("intro")
+ end,
+ world = function(world_id)
+ states.world.main:reset()
+ local menu_items = {
+ [1] = { name = "Map", },
+ [2] = { name = "Clonemon", },
+ [3] = { name = "bag", },
+ [4] = { name = "Player", },
+ [5] = { name = "Save", },
+ [6] = { name = "Settings", },
+ [7] = { name = "Quit", }
+ }
+ params = {
+ menu_items = menu_items,
+ world_id = world_id
+ }
+ temps.state = states.world
+ temps.ui = uis.world
+ end,
+ battle = function()
+ -- states.battle.intro:reset()
+ params = {
+ -- entry = "test",
+ -- moves = moves.charzard,
+ rivals_pokemon = {
+ [1] = {
+ name = "meowth",
+ },
+ },
+ my_pokemon = {
+ name = "charzard",
+ moves = moves.charzard,
+ level = 100,
+ },
+ player = {
+ name = "nyquist"
+ }
+ }
+ uis.world.paused = false
+ state = states.battle.enterBattle
+ temps.ui = uis.battle
+ end,
+ enter_text = function()
+ params = {
+ character_limit = 18,
+ title = "enter name: ",
+ sprite = "axolotl.png"
+ }
+ states.enter_text.main:reset()
+ -- temps.state = states.enter_text.main
+ state = states.enter_text.main
+ temps.ui = uis.enter_text
+ end,
+ choice_select = function()
+ params = {
+ sprite = "choice_select_test_one.png",
+ count = 2
+ -- sprite = "choice_select_test_two.png",
+ -- count = 3
+ }
+ states.choice_select.main:reset()
+ -- temps.state = states.choice_select.main
+ state = states.choice_select.main
+ temps.ui = uis.choice_select
+ end,
+ bag = function()
+ states.bag.main:reset()
+ state = states.bag.main
+ temps.ui = uis.bag
+ params = {
+ items = {
+ [1] = {
+ name = "book",
+ description = "can read it",
+ image = "",
+ quantity = 1
+ },
+ [2] = {
+ name = "cup",
+ description = "drink things",
+ image = "",
+ quantity = 2
+ },
+ [3] = {
+ name = "pencil",
+ description = "write things",
+ image = "",
+ quantity = 3
+ }
+ },
+ berries = {
+ [1] = {
+ name = "blueberry",
+ description = "improves stats",
+ image = "",
+ quantity = 1
+ },
+ [2] = {
+ name = "raseberry",
+ description = "raises defense stat",
+ image = "",
+ quantity = 2
+ },
+ [3] = {
+ name = "blackberry",
+ description = "clears status effects",
+ image = "",
+ quantity = 3
+ }
+ },
+ cloneballs = {
+ [1] = {
+ name = "ULTRA BALL",
+ description = "A better Ball with a higher catch rate than a Great Ball",
+ image = "",
+ quantity = 1
+ },
+ [2] = {
+ name = "NET BALL",
+ description = "A BALL that works on WATER- and BUG- type Clonemon",
+ image = "",
+ quantity = 2
+ },
+ }
+ }
+ end,
+ party = function()
+ states.party.main:reset()
+ params = {
+ my_clonemon = my_clonemon
+ }
+ state = states.party.main
+ temps.ui = uis.party
+ end,
+ start_menu = function()
+ states.start_menu.main:reset()
+ state = states.start_menu.main
+ temps.ui = uis.start_menu
+ end,
+ settings = function()
+ states.settings.main:reset()
+ state = states.settings.main
+ temps.ui = uis.settings
+ end,
+ partybox = function()
+ states.partybox.main:reset()
+ state = states.partybox.main
+ temps.ui = uis.partybox
+ end
+}
--- /dev/null
+local libterminal = require("extensions.libterminal")
+return libterminal
--- /dev/null
+local libtext = require("extensions.libtext")
+return libtext
--- /dev/null
+Copy = require("modules/copy")
+Find = require("modules/find")
+State = require("modules/state")
+Collection = require("modules/collection")
+world = require("modules.world")
+require("modules/string")
+require("modules/table")
+require("extensions")
+require("./uis")
+require("./states")
+
+state_collection = Collection:new()
+ui_collection = Collection:new()
+params_collection = Collection:new()
+params = {}
+
+function Push_state()
+ state_collection:push(state)
+ ui_collection:push(ui)
+ params_collection:push(params)
+end
+
+function Pop_state()
+ if not (state_collection.size > 0) then return end
+ state = state_collection:pop()
+ temps.ui = ui_collection:pop()
+ params = params_collection:pop()
+end
+
+
+unscaled_window_size = {w = 240, h = 160}
+window_size = {w = unscaled_window_size.w * Ex.Config.resolution_scale, h = unscaled_window_size.h * Ex.Config.resolution_scale}
+
+Speed_options = {
+ [1] = .25,
+ [2] = .5,
+ [3] = .75,
+ [4] = 1,
+ [5] = 1.25,
+ [6] = 1.5,
+ [7] = 1.75,
+ [8] = 2,
+ [9] = 2.5,
+ [10] = 2.75,
+ [11] = 3,
+}
+
+nyq.init(
+ "clonemon",
+ {x = 400, y = 100},
+ window_size,
+ {
+ -- frame_rate = 60 * (1 / Ex.Config.db.speed),
+ -- frame_rate = 60 * (1 / Speed_options[Ex.Config.db.speed]),
+ frame_rate = 60 / Speed_options[Ex.Config.db.speed],
+ controls = {
+ [1] = Ex.Config.mappings
+ },
+ fullscreen = Ex.Config.fullscreen,
+ assign_controllers = {
+ [1] = {controller = Ex.Config.controller, id = 0},
+ }
+ }
+)
+
+uis.start:init(unscaled_window_size, {scale = Ex.Config.resolution_scale})
+uis.world:init("test", "spritesheet_indoors_1.png", unscaled_window_size, {scale = Ex.Config.resolution_scale})
+uis.battle:init("clonemon_battle_ui.png", unscaled_window_size, {scale = Ex.Config.resolution_scale})
+uis.loadsave:init("loadsave.png", unscaled_window_size, {scale = Ex.Config.resolution_scale})
+uis.enter_text:init(unscaled_window_size, {scale = Ex.Config.resolution_scale})
+uis.choice_select:init(unscaled_window_size, {scale = Ex.Config.resolution_scale})
+uis.bag:init(unscaled_window_size, {scale = Ex.Config.resolution_scale})
+uis.party:init(unscaled_window_size, {scale = Ex.Config.resolution_scale})
+uis.start_menu:init(unscaled_window_size, {scale = Ex.Config.resolution_scale})
+uis.settings:init(unscaled_window_size, {scale = Ex.Config.resolution_scale})
+uis.mapping:init(unscaled_window_size, {scale = Ex.Config.resolution_scale})
+uis.partybox:init("spritesheet_partybox.png", unscaled_window_size, {scale = Ex.Config.resolution_scale})
+
+-- selected = 1
+
+temps = {
+ ui = nil
+}
+moves = {
+ charzard = {
+ [1] = {name = "kick", pp = {remaining = 12, total = 50}, type = "fire"},
+ [2] = {name= "punch", pp = {remaining = 15, total = 20}, type = "physical"},
+ [3] = {name= "slash", pp = {remaining = 15, total = 40}, type = "metal"},
+ [4] = {name= "fly", pp = {remaining = 15, total = 10}, type = "flying"},
+ },
+ pikachu = {
+ [1] = {name = "sleep", pp = {remaining = 12, total = 50},
+
+ type = "psychic"},
+ [2] = {name= "static", pp = {remaining = 15, total = 20},
+ type = "electric"},
+ [3] = {name= "jump", pp = {remaining = 15, total = 40},
+ type = "flying"},
+ [4] = {name= "kick", pp = {remaining = 15, total = 10},
+ type = "physical"},
+ }
+}
+
+my_clonemon = {
+ [1] = {
+ name = "Charzard",
+ moves = moves.charzard,
+ max_hp = 100,
+ hp = 50,
+ level = 100,
+ },
+ [2] = {
+ name = "Pikachu",
+ moves = moves.charzard,
+ max_hp = 50,
+ hp = 10,
+ level = 30,
+ },
+ [3] = {
+ name = "um",
+ moves = moves.charzard,
+ max_hp = 50,
+ hp = 10,
+ level = 30,
+ },
+ [4] = {
+ name = "Meowth",
+ moves = moves.charzard,
+ max_hp = 90,
+ hp = 50,
+ level = 30,
+ },
+ [5] = {
+ name = "Thing",
+ moves = moves.charzard,
+ max_hp = 90,
+ hp = 50,
+ level = 30,
+ },
+ [6] = {
+ name = "not thing",
+ moves = moves.charzard,
+ max_hp = 90,
+ hp = 50,
+ level = 30,
+ },
+}
+
+
+temps.ui = uis.start
+
+uis.world.ai:setPlayerPosition({x = 0 , y = 0})
+state = states.start.main
+
+local padding = 11
+local padding_top_and_bottom = 8
+Ex.Loops.init()
+local start = true
+
+local loop_id = Ex.Loops.add(60)
+local test_text = [[hello there! this is just a lot of text just for the heck of it I hope it doesn't annoy you at all, it is just what happens when you have a lot of text. Isn't this game really cool! Can't believe that everything seems to be working so smoothly. What is your name? oh cool. that is a nice name. hope that you can continue your adventure. What in the world is this? That is not normal though. ahahahah.]]
+ c = require("extensions.terminal.commands")
+while not nyq.quit do
+ Ex.Loops.loopStart(loop_id)
+
+ if temps.ui then
+
+ if ui and ui.free then
+ ui:free()
+ end
+
+ temps.ui:start(params)
+
+ ui = temps.ui
+
+ temps.ui = nil
+ end
+ if state then
+ state()
+ end
+ if not start then
+ if ((nyq.getGamepads() == nil) or (nyq.getGamepads()[1] == nil)) and (Ex.Config.db.controller ~= "none") then
+ Ex.Config.controller = "none"
+ nyq.controllerChange(0, "none");
+ end
+
+ if
+ (Ex.Config.controller == "none") and
+ (Ex.Config.db.controller ~= "none") and
+ (nyq.getGamepads() ~= nil) and
+ (nyq.getGamepads()[1] ~= nil)
+ then
+ Ex.Config.controller = Ex.Config.db.controller
+ nyq.controllerChange(0, Ex.Config.db.controller);
+ end
+
+ if
+ (Ex.Config.controller ~= "none") and
+ (Ex.Config.db.controller == "none")
+ then
+ Ex.Config.controller = "none"
+ nyq.controllerChange(0, "none");
+ end
+
+ if not ui.isChangeingInput then
+ nyq.controlsUpdate(0)
+ end
+ end
+ nyq.clear({r = 0, g = 0, b = 0, a = 255})
+ if ui == uis.battle then
+ ui:updateBackground()
+ ui:updateMyHealth()
+
+ if (state == states.battle.enterBattle) then
+ ui:updateNarration("enter_battle")
+ elseif (state == states.battle.doSelect) then
+ -- ui:updateDo(selected)
+ ui:updateDo()
+ elseif (state == states.battle.moveSelect) then
+ -- ui:updateMoveSelect(selected)
+ ui:updateMoveSelect()
+ end
+
+ elseif ui == uis.world then
+ ui:worldUpdate()
+
+ if state == states.world.option then
+ ui:textUpdate(test_text)
+ ui:selectUpdate({"yes", "no"})
+ end
+ if state == states.world.pause then
+ ui:pauseUpdate()
+ elseif state == states.world.text then
+ ui:textUpdate(test_text)
+ end
+
+ elseif ui == uis.start then
+ start = uis.start:update()
+ elseif ui == uis.party then
+ if state == states.party.main then
+ ui:partyUpdate()
+ elseif state == states.party.doWhat then
+ ui:doWhatUpdate()
+ elseif state == states.party.switch then
+ ui:switchUpdate()
+ end
+ else
+ ui:update()
+ end
+
+ nyq.draw()
+ Ex.Loops.loopEnd(loop_id)
+ end
+
--- /dev/null
+return {
+ zoom_in = "I",
+ zoom_out = "O",
+ move_left = "A",
+ move_right = "D",
+ move_up = "W",
+ move_down = "S",
+ save = "LCTRL S",
+ toggle_info = "C",
+ add_object = "LALT O",
+ toggle_object_select = "LSHIFT Tab",
+ next = "N",
+ previous = "P",
+ -- any popup can be toggled to fullscreen
+ delete = "Delete",
+ toggle_fullscreen = "LSHIFT Return",
+ position_reset = "R",
+ mode_place = "1",
+ mode_select = "2",
+ mode_move = "3"
+}
--- /dev/null
+return {
+ chest = {
+ crops = {
+ [1] = {x = 5, y = 4, w = 24, h = 18},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 6, w = 24, h = 8},
+ is_collidable = true,
+ is_visable = true,
+ },
+ nightstand = {
+ crops = {
+ [1] = {x = 102, y = 145, w = 16, h = 26},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 0, w = 16, h = 24},
+ is_collidable = true,
+ is_visable = true,
+ },
+ recliner = {
+ crops = {
+ [1] = {x = 35, y = 2, w = 24, h = 25},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 0, w = 24, h = 16},
+ is_collidable = true,
+ is_visable = true,
+ },
+ couch_forward = {
+ crops = {
+ [1] = {x = 62, y = 2, w = 32, h = 25},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 12, w = 28, h = 9},
+ is_collidable = true,
+ is_visable = true,
+ },
+ wood_flooring = {
+ crops = {
+ [1] = {x = 87, y = 107, w = 32, h = 16},
+ },
+ -- z and y of hit boIdead ks TF2 x are reltitive to crop x and y
+ hitbox = {x = 0, y = 0, w = 0, h = 0},
+ is_collidable = false,
+ is_visable = true,
+ },
+ rug = {
+ crops = {
+ [1] = {x = 0, y = 197, w = 48, h = 9},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 0, w = 48, h = 9},
+ is_collidable = false,
+ is_visable = true,
+ },
+ fridge = {
+ crops = {
+ [1] = {x = 0, y = 206, w = 32, h = 50},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 0, w = 32, h = 40},
+ is_collidable = true,
+ is_visable = true,
+ },
+ couch_side = {
+ crops = {
+ [1] = {x = 105, y = 23, w = 16, h = 49},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 14, w = 16, h = 22},
+ is_collidable = true,
+ is_visable = true,
+ },
+ flower_pot = {
+ crops = {
+ [1] = {x = 107, y = 4, w = 8, h = 17},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ -- hitbox = {x = 0, y =0, w = 8, h = 17},
+ hitbox = {x = 0, y = 12, w = 8, h = 5},
+ is_collidable = true,
+ is_visable = true,
+ },
+ oven = {
+ crops = {
+ [1] = {x = 3, y = 25, w = 24, h = 34},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 0, w = 24, h = 32},
+ is_collidable = true,
+ is_visable = true,
+ },
+ microwave = {
+ crops = {
+ [1] = {x = 43, y = 38, w = 32, h = 18},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 0, w = 32, h = 16},
+ is_collidable = true,
+ is_visable = true,
+ },
+ kitchen_table = {
+ crops = {
+ [1] = {x = 4, y = 75, w = 56, h = 26},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ -- hitbox = {x = 0, y = 8, w = 56, h = 12},
+ hitbox = {x = 0, y = 4, w = 56, h = 14},
+ is_collidable = true,
+ is_visable = true,
+ },
+ kitchen_chair = {
+ crops = {
+ [1] = {x = 68, y = 56, w = 16, h = 42},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 23, w = 18, h = 8},
+ is_collidable = true,
+ is_visable = true,
+ },
+ pillow = {
+ crops = {
+ [1] = {x = 92, y = 79, w = 32, h = 18},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 0, w = 0, h = 0},
+ is_collidable = false,
+ is_visable = true,
+ },
+ pc = {
+ crops = {
+ [1] = {x = 5, y = 109, w = 32, h = 32},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 0, w = 32, h = 32},
+ is_collidable = false,
+ is_visable = true,
+ },
+ framed_photo = {
+ crops = {
+ [1] = {x = 50, y = 109, w = 32, h = 20},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 0, w = 0, h = 0},
+ is_collidable = false,
+ is_visable = true,
+ },
+ bed = {
+ crops = {
+ [1] = {x = 0, y = 146, w = 24, h = 51},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 10, w = 24, h = 32},
+ is_collidable = true,
+ is_visable = true,
+ },
+ bookshelf = {
+ crops = {
+ [1] = {x = 24, y = 146, w = 40, h = 33},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 8, w = 40, h = 20},
+ is_collidable = true,
+ is_visable = true,
+ },
+ desk = {
+ crops = {
+ [1] = {x = 43, y = 225, w = 48, h = 26},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 0, w = 32, h = 12},
+ is_collidable = true,
+ is_visable = true,
+ },
+}
--- /dev/null
+return {
+ house1 = {
+ crops = {
+ [1] = {x = 0, y = 2, w = 98, h = 111},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 43, w = 98, h = 37},
+ is_collidable = true,
+ is_visable = true,
+ },
+ house2 = {
+ crops = {
+ [1] = {x = 100, y = 0, w = 115, h = 98},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 35, w = 115, h = 45},
+ is_collidable = true,
+ is_visable = true,
+ },
+ house3 = {
+ crops = {
+ [1] = {x = 172, y = 99, w = 140, h = 108},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 3, y = 11, w = 134, h = 72},
+ is_collidable = true,
+ is_visable = true,
+ },
+ house4 = {
+ crops = {
+ [1] = {x = 0, y = 113, w = 150, h = 103},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 30, w = 150, h = 57},
+ is_collidable = true,
+ is_visable = true,
+ },
+ shack = {
+ crops = {
+ [1] = {x = 150, y = 149, w = 22, h = 36},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 2, w = 22, h = 14},
+ is_collidable = true,
+ is_visable = true,
+ },
+ well = {
+ crops = {
+ [1] = {x = 320, y = 0, w = 67, h = 48},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 0, y = 20, w = 67, h = 15},
+ is_collidable = true,
+ is_visable = true,
+ },
+ tree_1 = {
+ crops = {
+ [1] = {x = 393, y = 0, w = 61, h = 106},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 16, y = 90, w = 23, h = 12},
+ is_collidable = true,
+ is_visable = true,
+ },
+ tree_2 = {
+ crops = {
+ [1] = {x = 463, y = 0, w = 106, h = 121},
+ },
+ -- z and y of hit box are reltitive to crop x and y
+ hitbox = {x = 42, y = 96, w = 31, h = 10},
+ is_collidable = true,
+ is_visable = true,
+ },
+ rng_hospital = {
+ crops = {
+ [1] = {x = 319, y = 106, w = 119, h = 113}
+ },
+ hitbox = {x = 0, y = 0, w = 119, h = 113},
+ is_collidable = true,
+ is_visable = false
+ }
+}
--- /dev/null
+spritesheet = "spritesheet_indoors_1.png"
+world_name = "test"
+keys = require("map_configs.controls.controls")
+map = { grid = 8, width = 240 * 2, height = 88 * 2 }
+objects = require("map_configs.crops.indoor")
--- /dev/null
+spritesheet = "spritesheet_outdoor_1.png"
+world_name = "test"
+keys = require("map_configs.controls.controls")
+map = {grid = 8, width = 480 * 2, height = 320 * 2}
+objects = require("map_configs.crops.outdoor")
--- /dev/null
+local ai_mt = {}
+local objectCollision = nil
+local colliding_id = nil
+local noClip = false
+
+function ai_mt:travel(direction)
+ if not objectCollision then return end
+ self.entity.idle = "idle_" .. direction
+ self.entity.move = "walk_" .. direction
+
+ local checkCollision = nil
+ local distance = (self.entity.speed * nyq.deltaTime)
+
+ local a, b = 0, 0
+ local t = nil
+ if direction == "north" then
+ collisionCheck = objectCollision.hit_bottom
+ a = distance
+ b = distance
+ t = "y"
+ elseif direction == "south" then
+ collisionCheck = objectCollision.hit_top
+ a = -distance
+ b = -distance
+ t = "y"
+ elseif direction == "east" then
+ collisionCheck = objectCollision.hit_left
+ a = distance
+ b = -distance
+ t = "x"
+ elseif direction == "west" then
+ collisionCheck = objectCollision.hit_right
+ a = -distance
+ b = distance
+ t = "x"
+ end
+
+ if
+ objectCollision.is_collidable and
+ collisionCheck and
+ (not noClip) and
+ (not objectCollision.type:find("^rng_"))
+ then
+ return
+ end
+
+ self.entity.position[t] = self.entity.position[t] + a
+ self.world.position[t] = self.world.position[t] + b
+end
+
+function ai_mt:getPlayerPosition()
+ return {
+ x = -((self.world.position.x) / (1 / self.world.scaler)) +
+ self.entity.screen_position.x,
+ y = -((self.world.position.y) / (1 / self.world.scaler)) +
+ self.entity.screen_position.y
+ }
+end
+
+function ai_mt:setPlayerPosition(position)
+ self.world.position.x = -(position.x - self.entity.screen_position.x) *
+ (1 / self.world.scaler)
+ self.world.position.y = -(position.y - self.entity.screen_position.y) *
+ (1 / self.world.scaler)
+end
+
+function ai_mt:movePathSet(paths)
+ self.paths = Copy.deepcopy(paths)
+ for i, path in pairs(paths) do
+ self.paths[i].first_update = true
+ end
+end
+
+function ai_mt:movePathUpdate()
+ if not self.paths then return false end
+
+ for i, path in pairs(self.paths) do
+ if path.first_update then
+ path.start_pos = self:getPlayerPosition()
+ path.moving_pos = Copy.shallow_copy(self.paths[i].start_pos)
+ path.first_update = false
+ end
+ if
+ (path.direction == "north" and
+ path.start_pos.y - path.moving_pos.y >= path.distance)
+ or
+ (path.direction == "east" and
+ path.moving_pos.x - path.start_pos.x >= path.distance)
+ or
+ (path.direction == "south" and
+ -(path.start_pos.y - path.moving_pos.y) >= path.distance)
+ or
+ (path.direction == "west" and
+ path.start_pos.x - path.moving_pos.x >= path.distance)
+ then
+ self.path = nil
+ return true
+ end
+ path.moving_pos = self:getPlayerPosition()
+ self:travel(path.direction)
+ self:collisionUpdate()
+ end
+
+ return false
+end
+
+function ai_mt:init(world, entity, scale, window_size)
+ self.paths = nil
+ self.paths_callback = nil
+ self.entity = entity
+ self.world = world
+ self.scale = scale
+ self.loop_id = Ex.Loops.add(60)
+end
+
+function ai_mt:setNoClip(value)
+ noClip = value
+end
+
+function ai_mt:start()
+ colliding_id = nyq.world.addCollisionCheck( 0, {
+ x = self.entity.screen_position.x * self.scale + (self.scale * 1),
+ y = self.entity.screen_position.y * self.scale + (self.scale * 7)
+ }, self.entity.hitbox)
+end
+
+function ai_mt:collisionUpdate()
+ objectCollision = nyq.world.checkCollision(0, colliding_id)
+ -- print(objectCollision.type);
+end
+
+return ai_mt
--- /dev/null
+local time = {}
+
+function time.start()
+ time.start = os.clock()
+end
+
+function time.get()
+ time.start = os.clock()
+end
+
+return time
--- /dev/null
+local Collection = {}
+
+function Collection:new()
+ local o = {}
+ o.metatable = {
+ __index = {
+
+ collection = {},
+ elapsed_time = 0,
+ addedNew = false,
+ size = 0,
+
+ push = function(self, st)
+ self.collection[#self.collection + 1] = st
+ self.addedNew = true
+ self.size = self.size + 1
+ end,
+
+ pop = function(self)
+ local state = table.remove(self.collection, self.size)
+ if state then
+ -- state.first_call = true
+ self.first_call = true
+ self.addedNew = false
+ self.size = self.size - 1
+ end
+ return state
+ end
+ },
+ }
+ setmetatable(o, o.metatable)
+ return o
+end
+
+return Collection
--- /dev/null
+local copy = {}
+
+function copy.shallow_copy(t)
+ local t2 = {}
+ for k,v in pairs(t) do
+ t2[k] = v
+ end
+ return t2
+end
+
+
+function copy.deepcopy(orig, copies)
+ copies = copies or {}
+ local orig_type = type(orig)
+ local c
+ if orig_type == 'table' then
+ if copies[orig] then
+ c = copies[orig]
+ else
+ c = {}
+ copies[orig] = c
+ for orig_key, orig_value in next, orig, nil do
+ c[copy.deepcopy(orig_key, copies)] = copy.deepcopy(orig_value, copies)
+ end
+ setmetatable(c, copy.deepcopy(getmetatable(orig), copies))
+ end
+ else -- number, string, boolean, etc
+ c = orig
+ end
+ return c
+end
+
+return copy
--- /dev/null
+local find = {}
+
+function find.reverse(str, pattern)
+ local reversed = string.reverse(str)
+ local match = table.pack(string.find(reversed, pattern))
+ if match[1] and match[2] then
+ match[1] = string.len(str) - match[1] + 1
+ match[2] = string.len(str) - match[2] + 1
+ return match
+ end
+ return nil
+end
+
+return find
--- /dev/null
+local hashTable = {}
+hashTable.key_values = {}
+
+function hashTable:insert(t, v)
+ local hexstring = hashTable:getString(t)
+ hashTable.key_values[hexstring] = v
+end
+
+function hashTable:getString(t)
+ local hexout = tostring(t)
+ return hexout:sub(hexout:find("0x.*"))
+end
+function hashTable:getValue(t)
+ local hexstring = hashTable:getString(t)
+ return hashTable.key_values[hexstring]
+end
+
+return hashTable
--- /dev/null
+local entity = {}
+
+local crop_size = nil
+entity.name = nil
+
+function entity:Entityinit(ui, name, spritesheet, scale, scaler, window_size)
+ self.position = {}
+ self.position.x = 0
+ self.position.y = 0
+ self.speed = 600
+ self.idle = "idle_south"
+ self.scaler = scaler
+ self.move = nil
+ self.start_position = {x = 0, y = 0}
+ self.screen_position = {
+ x = window_size.w / 2,
+ y = window_size.h / 2
+ -- x = 0,
+ -- y = 0
+ }
+ self.crop_size = {w = 44 * .35, h = 57 * .35}
+ self.size = {w = 44 * .35, h = self.crop_size.h + 2}
+ self.hitbox = { w = 13 * scale, h = 14 * scale}
+ self.objectCollision = nil
+ self.spritesheet = spritesheet
+ self.name = name
+
+end
+
+function entity:EntityStart(ui)
+
+ ui:addAnimation(self.name, "walk_north", {
+ {x = 0, y = 0, w = 44, h = 57},
+ {x = 0, y = 58, w = 44, h = 57},
+ {x = 0, y = 0, w = 44, h = 57},
+ {x = 0, y = 116, w = 44, h = 57},
+ }, self.crop_size)
+
+ ui:addAnimation(self.name, "idle_north", {
+ {x = 0, y = 0, w = 44, h = 57},
+ }, self.crop_size)
+
+ ui:addAnimation(self.name, "walk_east", {
+ {x = 44, y = 0, w = 44, h = 57},
+ {x = 44, y = 57, w = 44, h = 57},
+ {x = 44, y = 116, w = 44, h = 57},
+ }, self.crop_size)
+
+ ui:addAnimation(self.name, "idle_east", {
+ {x = 44, y = 0, w = 44, h = 57},
+ }, self.crop_size)
+
+ ui:addAnimation(self.name, "walk_south", {
+ {x = 88, y = 0, w = 44, h = 57},
+ {x = 88, y = 58, w = 44, h = 57},
+ {x = 88, y = 0, w = 44, h = 57},
+ {x = 88, y = 116, w = 44, h = 57},
+ }, self.crop_size)
+
+ ui:addAnimation(self.name, "idle_south", {
+ {x = 88, y = 0, w = 44, h = 57},
+ }, self.crop_size)
+
+ ui:addAnimation(self.name, "walk_west", {
+ {x = 132, y = 0, w = 44, h = 57},
+ {x = 132, y = 58, w = 44, h = 57},
+ {x = 132, y = 116, w = 44, h = 57},
+ }, self.crop_size)
+
+ ui:addAnimation(self.name, "idle_west", {
+ {x = 132, y = 0, w = 44, h = 57},
+ }, self.crop_size)
+end
+
+function entity:getPosition()
+ return {
+ x = (self.position.x * self.scaler) ,
+ y = (self.position.y * self.scaler)
+ }
+end
+
+function entity:setPosition(id, position)
+ self.position = {
+ x = (position.x) * (1 / self.scaler),
+ y = (position.y) * (1 / self.scaler),
+ }
+end
+
+function entity:EntityMoveUpdate(ui)
+
+ if self.move then
+ local speed = 20
+ if
+ self.move == "walk_north" or
+ self.move == "nnwalk_south"
+ then
+ speed = 27
+ end
+ ui:updateAnimation(self.name,
+ self.move,
+ speed, self.screen_position)
+ else
+ ui:updateAnimation(self.name, self.idle,
+ 1, self.screen_position)
+ end
+
+
+ self.move = nil
+end
+
+return entity
--- /dev/null
+local player = {}
+local entity = require("modules.metatables.entity")
+
+local face_sprite_id = nil
+
+function player:init(ui, name, spritesheet, scale, scaler, window_size)
+ entity:Entityinit(ui, name, spritesheet, scale, scaler, window_size)
+ setmetatable(player, {__index = entity })
+end
+
+function player:start(ui)
+ player:EntityStart(ui)
+ face_sprite_id = ui:newSprite(self.spritesheet)
+ ui:spriteAddCrops(face_sprite_id, "face", 5, {
+ {
+ x = 0,
+ y = 173,
+ w = 50,
+ h = 30
+ }
+ })
+end
+
+function player:faceUpdate(ui)
+ ui:spriteUpdateCrop(face_sprite_id, "face", 1, {
+ x = 0, y = 130
+ })
+end
+
+function player:moveUpdate(ui)
+ player:EntityMoveUpdate(ui)
+end
+
+return player
--- /dev/null
+local State = {}
+
+function State:new(call)
+ local o = {}
+ o.metatable = {
+ __index = {
+ first_call = true,
+ elapsed_time = 0,
+ start_time = 0,
+ },
+ __call = function(table, key)
+ if table.first_call then
+ table.start_time = nyq.getTicks()
+ table.first_call = false
+ end
+ call()
+ -- table.elapsed_time = os.clock() - table.start_time
+ table.elapsed_time = nyq.getTicks() - table.start_time
+ end
+
+ }
+ o.reset = function()
+ o.start_time = nyq.getTicks()
+ o.first_call = true
+ o.elapsed_time = 0
+
+ end
+ setmetatable(o, o.metatable)
+ return o
+end
+
+return State
--- /dev/null
+string.WordWrap = function (text, character_length)
+ local str = text
+ local spaces = {}
+ local i = 1
+ local lines = {}
+
+ local found = nil
+ local total = 0
+ repeat
+ found = string.find(str, '%s')
+ if found then
+ total = total + found
+ spaces[i] = total
+ str = string.sub(str, found + 1)
+ end
+ i = i + 1
+ until not found
+
+ local start = 1
+ found = 0
+ i = 1
+ for k, v in pairs(spaces) do
+ if v > start + character_length then
+ found = spaces[k - 1]
+ local line = string.sub(text, start, found)
+ if string.len(line) > 0 then
+ lines[i] = line
+ i = i + 1
+ end
+ start = found + 1
+ end
+ end
+ local line = string.sub(text, start)
+ if string.len(line) > 0 then
+ local match = Find.reverse(line, '%s')
+ if string.len(line) > character_length then
+ if match then
+ lines[i] = string.sub(line, 1, match[1])
+ lines[i + 1] = string.sub(line, match[1] + 1)
+ end
+ else
+ lines[i] = line
+ end
+ end
+ -- if not lines then return {text} end
+
+ return lines
+end
--- /dev/null
+table.Reverse = function(a)
+ local b = {}
+ for i = 1, #a do
+ local j = #a - (i - 1)
+ b[j] = {}
+ b[j].id = i
+ b[j].text = a[i]
+ end
+ return b
+end
--- /dev/null
+local uuid = {}
+local random = math.random
+math.randomseed(os.time())
+
+function uuid:create()
+ local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
+ return string.gsub(template, '[xy]', function (c)
+ local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
+ return string.format('%x', v)
+ end)
+end
+return uuid
--- /dev/null
+local outdoor_crops = require("map_configs.crops.outdoor")
+local world = {}
+local map_spec = {}
+local locations = {}
+world.current_pos = 1
+world.entity = nil
+world.position = {x = 0, y = 0}
+world.scaler = .100
+world.zIndex = 0
+local grid = 4
+local grid_size = grid * grid
+world.layout = {}
+local world_size = 0
+local world_offset = {x = 0, y = 0}
+local maps = {}
+local window_size = nil
+local spritesheet_id = nil
+
+-- local LN <const> = 0
+local N <const> = 2
+local S <const> = 3
+local E <const> = 4
+local W <const> = 5
+
+local map_specs = nil
+
+local update = {}
+update[N] = false
+update[E] = false
+update[S] = false
+update[W] = false
+
+local first = {}
+first[N] = true
+first[E] = true
+first[S] = true
+first[W] = true
+first[N << E] = true
+first[S << E] = true
+first[N << W] = true
+first[S << W] = true
+
+local spritesheet = nil
+local name = nil
+
+-- map_specs example
+-- local map_specs = {
+-- [1] = {spec = {1, 2, 3}, limit = 30},
+-- [2] = {spec = {4, 5, 6}, limit = 14},
+-- }
+
+local function getCardinal(n)
+ return {
+ [N] = ((n + grid) <= grid_size) and (n + grid) or -1,
+ [E] = ((n % grid) < (grid - 1)) and (n + 1) or -1,
+ [S] = ((n - grid) > 0) and (n - grid) or -1,
+ [W] = (((n - 1) % grid) > 0) and (n - 1) or -1,
+ }
+end
+
+local function getOrdinal(n)
+ local x = ((n - 1) % grid) + 1
+
+ return {
+ [N << E] =
+ ((x < grid) and (n + grid <= grid_size)) and
+ (n + grid + 1) or -1,
+
+ [S << E] =
+ ((n + grid) > (grid * 2) and (x <= 3)) and
+ (n - grid + 1) or -1,
+
+ [S << W] =
+ ((n + grid > grid * 2) and (x > 1)) and
+ (n - grid - 1) or -1,
+
+ [N << W] =
+ ((x > 1) and (n + grid <= grid_size)) and
+ (n + grid - 1) or -1,
+ }
+end
+
+function world:init(g, e, specs, ws, s, n)
+ grid = g
+ grid_size = g * g
+ map_specs = specs
+ window_size = ws
+ spritesheet = s
+ name = n
+ self.current_pos = 1
+ self.entity = e
+ nyq.world.init(0, spritesheet, name);
+end
+
+function world:read(map_ip, pos, zIndex)
+ nyq.world.read(map_ip, self.layout[pos].id, zIndex)
+
+ local rng = self.layout[pos].rng
+ if rng ~= nil then
+ nyq.world.newObject(map_ip, rng)
+ end
+end
+
+function world:mapStart(ui)
+ if not self.layout[self.current_pos] then
+ print("could not load map")
+ os.exit()
+ end
+ nyq.world.free(0)
+ for i = 0, 8 do
+ nyq.world.init(i, spritesheet, name);
+ end
+
+ spritesheet_id = ui:newSprite("spritesheet_outdoor_1.png")
+ self:read(0, self.current_pos, 0)
+end
+
+function world:getPosition()
+ return {
+ x = (self.position.x * self.scaler) ,
+ y = (self.position.y * self.scaler)
+ }
+end
+
+
+function world:setPosition(id, position)
+ nyq.map.set(id, {
+ x = (position.x) * (1 / self.scaler),
+ y = (position.y) * (1 / self.scaler),
+ })
+end
+
+
+local function getOpposite(d)
+ return (d == N) and S or
+ (d == S) and N or
+ (d == W) and E or
+ (d == E) and W
+end
+
+function world:createRNGObject(ui, id, variations)
+ local world_pos = self:getPosition()
+ local start_x = ((self.current_pos - 1) % grid ) * 480
+ local start_y = (math.floor((self.current_pos - 1) / grid)) * 320
+ local update_pos = {x = world_pos.x + start_x, y = world_pos.y - start_y}
+ nyq.world.read(0, id, 0)
+
+ for i, object in pairs(nyq.world.getObjects(0)) do
+ for type, variation in pairs(variations) do
+ if object.type == "rng_" .. type then
+ local v = math.floor((math.random() * #variation) + 1)
+ local a = Copy.deepcopy(outdoor_crops[variation[v]])
+ a.size = {
+ w = a.crops[1].w * (1 / self.scaler),
+ h = a.crops[1].h * (1 / self.scaler)
+ }
+ a.hitbox = {
+ x = a.hitbox.x * (1 / self.scaler),
+ y = a.hitbox.y * (1 / self.scaler),
+ w = a.hitbox.w * (1 / self.scaler),
+ h = a.hitbox.h * (1 / self.scaler)
+ }
+ a.type = variation[v]
+ a.position = object.position
+ return a
+ end
+ end
+ end
+ return nil
+end
+
+function world:mapUpdate(ui, args)
+::MAP_CHANGE::
+ local world_pos = self:getPosition()
+ local cardinal = getCardinal(self.current_pos)
+ local ordinal = getOrdinal(self.current_pos)
+ local entity_pos = self.entity:getPosition()
+ local start_x = ((self.current_pos - 1) % grid ) * 480
+ local start_y = (math.floor((self.current_pos - 1) / grid)) * 320
+ local update_pos = {x = world_pos.x + start_x, y = world_pos.y - start_y}
+
+ update[N] = update_pos.y > 0
+ update[S] = -update_pos.y > window_size.h
+ update[E] = -update_pos.x > window_size.w
+ update[W] = update_pos.x > 0
+
+ if (update[N] and update[E]) then
+ ordinal_map_ip = 5
+ elseif (update[S] and update[E]) then
+ ordinal_map_ip = 6
+ elseif (update[N] and update[W]) then
+ ordinal_map_ip = 7
+ elseif (update[S] and update[W]) then
+ ordinal_map_ip = 8
+ end
+
+ for k, v in pairs(update) do
+ if not update[k] then
+ first[k] = true
+ end
+ end
+
+ for i = N, S do for j = E, W do
+ if (not update[i]) and (not update[j]) then
+ first[i << j] = true
+ end
+ end end
+
+ for d1 = N, S do
+ for d2 = E, W do
+ local offset = {x = 0, y = 0}
+ if update[d1] and update[d2] and self.layout[ordinal[d1 << d2]] then
+ if d1 == N and d2 == E then
+ offset.x = 480
+ offset.y = -320
+ elseif d1 == S and d2 == E then
+ offset.x = 480
+ offset.y = 320
+ elseif d1 == S and d2 == W then
+ offset.x = -480
+ offset.y = 320
+ elseif d1 == N and d2 == W then
+ offset.x = -480
+ offset.y = -320
+ end
+
+ if first[d1 << d2] then
+ -- nyq.world.read(ordinal_map_ip, self.layout[ordinal[d1 << d2]].id, 0)
+ self:read(ordinal_map_ip, ordinal[d1 << d2], 0)
+ first[d1 << d2] = false
+ end
+ -- local rng = self.layout[ordinal[d1 << d2]].rng
+ -- if rng then
+ -- ui:spriteUpdateCrop(spritesheet_id, rng.name, 1, {
+ -- x = update_pos.x + rng.position.x + offset.x,
+ -- y = update_pos.y + rng.position.y + offset.y,
+ -- })
+ -- end
+ world:setPosition(ordinal_map_ip, {
+ x = update_pos.x + offset.x,
+ y = update_pos.y + offset.y,
+ })
+ nyq.world.update(ordinal_map_ip, args.scale * self.scaler)
+ end
+ end
+ end
+
+
+ for d = N, W do
+ local cardinal_map_ip = d - 1
+ if update[d] and self.layout[cardinal[d]] then
+ local offset = { x = 0, y = 0 }
+ local pass = false
+
+ if d == N then
+ offset.y = -320
+ pass = -entity_pos.y + start_y + self.entity.size.h < 0
+ elseif d == E then
+ offset.x = 480
+ pass = entity_pos.x - start_x > 480
+ elseif d == S then
+ offset.y = 320
+ pass = -entity_pos.y + start_y > 320
+ elseif d == W then
+ offset.x = -480
+ pass = entity_pos.x - start_x + self.entity.size.h < 0
+ end
+
+ if pass then
+ -- nyq.world.read(0, self.layout[cardinal[d]].id, 0)
+ self:read(0, cardinal[d], 0)
+ for i = N, W do
+ first[i] = true
+ first[i << W] = true
+ first[i << E] = true
+ end
+ self.current_pos = cardinal[d]
+ world:print()
+ print("\n")
+ goto MAP_CHANGE
+ end
+
+ if first[d] then
+ print('first')
+ -- nyq.world.read(cardinal_map_ip, self.layout[cardinal[d]].id, 0)
+ self:read(cardinal_map_ip, cardinal[d], 0)
+ first[d] = false
+ end
+
+ -- local rng = self.layout[cardinal[d]].rng
+ -- if rng then
+ -- ui:spriteUpdateCrop(spritesheet_id, rng.name, 1, {
+ -- x = update_pos.x + rng.position.x + offset.x,
+ -- y = update_pos.y + rng.position.y + offset.y,
+ -- })
+ -- end
+
+ world:setPosition(cardinal_map_ip, {
+ x = update_pos.x + offset.x,
+ y = update_pos.y + offset.y,
+ })
+ nyq.world.update(cardinal_map_ip, args.scale * self.scaler)
+ end
+ end
+
+ world:setPosition(0, update_pos)
+ nyq.world.update(0, args.scale * self.scaler)
+
+
+end
+
+function world:generate(ui, variations)
+ math.randomseed()
+
+ local done = 1
+ local pos = self.current_pos
+
+ for k, v in pairs(map_specs) do
+ done = done + v.limit
+ end
+
+ if done > grid_size then done = grid_size end
+
+ while(world_size < done - 1) do
+
+::CONTINUE::
+
+ for k, v in pairs(map_specs) do
+
+ if v.limit <= 0 then
+ table.remove(map_specs, k)
+ goto CONTINUE
+ end
+
+ local s = getCardinal(pos)
+
+ local map_id = v.spec[math.floor(math.random() * (#v.spec - 1) + .5) + 1]
+
+ local check = {}
+ for _, dir in pairs(s) do
+ if dir > 0 then
+ table.insert(check, dir)
+ end
+ end
+
+ local check_count = 0
+ local n = 0
+
+
+::CHECKAGAIN::
+
+ local r = math.floor(math.random() * (#check - 1) + .5) + 1
+
+ if check_count >= grid_size * 10 then
+ return
+ else
+ for k, _ in pairs(self.layout) do
+ if k == check[r] then
+ check_count = check_count + 1
+ goto CHECKAGAIN
+ end
+ end
+ end
+ local object = self:createRNGObject(ui, map_id, variations)
+
+ -- TODO:
+ -- make rng an array of possible random objects
+ self.layout[pos] = {id = map_id, next_pos = check[r], rng = object}
+ pos = check[r]
+ v.limit = v.limit - 1
+ world_size = world_size + 1
+ end
+ end
+end
+
+function world:print()
+
+ local start = grid_size - grid + 1
+
+ for i = start, 1, -grid do
+ for j = i, i + grid - 1 do
+ if self.layout[j] then
+ if j == self.current_pos then
+ io.write(string.format(" [%.2d] ", self.layout[j].id))
+ else
+ io.write(" [==] ")
+ end
+ else
+ io.write(" [ ] ")
+ end
+ end
+ print("")
+ end
+
+
+end
+
+function world:free()
+ for i = 0, 8 do
+ nyq.world.free(i);
+ end
+end
+
+return world
+-- world:init(4, {
+-- [1] = {spec = {4, 5, 9}, limit = 4}
+-- })
+-- world:generate()
+-- world:print()
--- /dev/null
+local player_spritesheet <const> = "nyquist_spritesheet.png"
+local ai <const> = require("modules.ai")
+local map <const> = require("modules.map")
+local vars <const> = {}
+local assign = require("extensions.metatables.ui")
+local ui, ui_mt = assign("world", {vars = vars, ai = ai})
+
+function ui:init(world_name, world_spritesheet,
+ window_size, options)
+ ui_mt:_init(player_spritesheet, window_size, "NotoSansMono-Regular.ttf", 8,
+ options, function()
+ vars.world_spritesheet = world_spritesheet
+ vars.world_name = world_name
+ vars.selection_max = 0
+ vars.start_menu = {}
+ local pos = { x = ui.window_size.w - 55, y = 4 }
+ vars.start_menu.position = pos
+ vars.start_menu.selection = {}
+ vars.start_menu.size = {w = 0, h = 0}
+ vars.go_outside = false
+ vars.traverse_stairs = false
+ vars.in_door = false
+ vars.in_stairs = false
+ end)
+ ai:init(map, options.scale, window_size)
+ world:init(2, {
+ [1] = {spec = {3, 4, 5}, limit = 3},
+ })
+ world:generate()
+ print("world layout:\n")
+ world:print()
+ print()
+end
+
+function ui:startCallback()
+ nyq.hasFrameCap(true)
+ vars.selected = 1
+ vars.selection_rect = ui:createRect({r = 100, g = 0, b = 0, a = 50}, true, 6)
+ vars.text_rect_id = ui:createRect({r = 0, g = 0, b = 0, a = 200}, true, 4)
+ vars.text_pos = 0
+ vars.text_max = 0
+ vars.text_done = false
+ vars.text_end = false
+
+
+ for i = 1, 3 do
+ local id = string.format("%d", i)
+ ui:addText("text", id, " ", 5,
+ {r = 255, g = 255, b = 255, a = 255},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+ end
+
+ nyq.world.init(0, vars.world_spritesheet, vars.world_name);
+ nyq.world.read(0, params.world_id, ai.map.zIndex)
+
+ vars.face_sprite_id = ui:newSprite(ui.spritesheet)
+ ui:spriteAddCrops(vars.face_sprite_id, "face", 5, {
+ {
+ x = 0,
+ y = 173,
+ w = 50,
+ h = 30
+ }
+ })
+ ai:start()
+ if params.world_id == 1 then
+ vars.rect_id = ui:createRect({r = 0, g = 0, b = 0, a = 180}, true, 0)
+ end
+
+ ui:addAnimation("player", "walk_north", {
+ {x = 0, y = 0, w = 44, h = 57},
+ {x = 0, y = 58, w = 44, h = 57},
+ {x = 0, y = 0, w = 44, h = 57},
+ {x = 0, y = 116, w = 44, h = 57},
+ }, ai.player.crop_size)
+
+ ui:addAnimation("player", "idle_north", {
+ {x = 0, y = 0, w = 44, h = 57},
+ }, ai.player.crop_size)
+
+ ui:addAnimation("player", "walk_east", {
+ {x = 44, y = 0, w = 44, h = 57},
+ {x = 44, y = 57, w = 44, h = 57},
+ {x = 44, y = 116, w = 44, h = 57},
+ }, ai.player.crop_size)
+
+ ui:addAnimation("player", "idle_east", {
+ {x = 44, y = 0, w = 44, h = 57},
+ }, ai.player.crop_size)
+
+ ui:addAnimation("player", "walk_south", {
+ {x = 88, y = 0, w = 44, h = 57},
+ {x = 88, y = 58, w = 44, h = 57},
+ {x = 88, y = 0, w = 44, h = 57},
+ {x = 88, y = 116, w = 44, h = 57},
+ }, ai.player.crop_size)
+
+ ui:addAnimation("player", "idle_south", {
+ {x = 88, y = 0, w = 44, h = 57},
+ }, ai.player.crop_size)
+
+ ui:addAnimation("player", "walk_west", {
+ {x = 132, y = 0, w = 44, h = 57},
+ {x = 132, y = 58, w = 44, h = 57},
+ {x = 132, y = 116, w = 44, h = 57},
+ }, ai.player.crop_size)
+
+ ui:addAnimation("player", "idle_west", {
+ {x = 132, y = 0, w = 44, h = 57},
+ }, ai.player.crop_size)
+
+
+ vars.menu_size = #params.menu_items
+ vars.start_menu.id = ui:imageCreate("pause.png", 5)
+
+ local padding = 11
+ local padding_top_and_bottom = 8
+ local fg_color = {r = 0, g = 0, b = 0, a = 0}
+ local bg_color = {r = 255, g = 255, b = 255, a = 0}
+
+ for i, item in ipairs(params.menu_items) do
+ vars.start_menu.selection[i] = {}
+ vars.start_menu.selection[i].position = {x = vars.start_menu.position.x + 8, y = padding_top_and_bottom + padding * (i - 1)}
+ vars.start_menu.selection[i].id = nil
+ ui:addText2(vars.start_menu.selection[i], "id", item.name, 5, fg_color, bg_color)
+ end
+ local text_size = ui:getTextSize2(vars.start_menu.selection[1], "id")
+ vars.start_menu.size = {
+ w = 53, h = ((padding * (vars.menu_size - 1)) +
+ (padding_top_and_bottom)) + text_size.h
+ }
+end
+
+-- function ui:changeMap(id, spritesheet)
+function ui:changeMap(chunk)
+ nyq.clear({r = 0, g = 0, b = 0, a = 255})
+ nyq.draw()
+ states.world.main:reset()
+ ui:free()
+ ui:init(chunk.world, chunk.spritesheet,
+ unscaled_window_size,
+ {scale = Ex.Config.resolution_scale})
+ local menu_items = {
+ [1] = { name = "Map", },
+ [2] = { name = "Clonemon", },
+ [3] = { name = "bag", },
+ [4] = { name = "Player", },
+ [5] = { name = "Save", },
+ [6] = { name = "Settings", },
+ [7] = { name = "Quit", }
+ }
+ params = {
+ menu_items = menu_items,
+ world_id = chunk.id,
+ idle = "idle_south",
+ }
+ ui:start()
+ ai:setNoClip(true)
+
+ local start_pos = {
+ x = 24 - ai.player.size.w / 2 ,
+ y = -(ai.player.size.h / 2) - 20
+ }
+ ai:setPlayerPosition(start_pos)
+ ai:movePathSet(
+ {
+ [0] = {
+ direction = "south",
+ distance = 50
+ }
+ })
+ local loop_id = Ex.Loops.add(60)
+ repeat
+ Ex.Loops.loopStart(loop_id)
+ nyq.clear({r = 0, g = 0, b = 0, a = 255})
+ local noPath = ai:movePathUpdate()
+ ui:worldUpdate()
+ nyq.draw()
+ Ex.Loops.loopEnd(loop_id)
+ until noPath
+ ai:setNoClip(false)
+end
+
+function ui:worldUpdate()
+ -- do NOT load anything fram a group in here!
+ -- it will confilict with other uis
+ if ai.player.move then
+ local speed = 20
+ if
+ ai.player.move == "walk_north" or
+ ai.player.move == "walk_south"
+ then
+ speed = 27
+ end
+ ui:updateAnimation("player",
+ ai.player.move,
+ speed, ai.player.screen_position)
+ else
+ ui:updateAnimation("player", ai.player.idle,
+ 1, ai.player.screen_position)
+ end
+ local player_pos = ai:getPlayerPosition()
+ local map_pos = map:getPosition()
+ if params.world_id == 1 then
+ ui:rectUpdate(vars.rect_id,
+ {x = map_pos.x + 112, y = map_pos.y + 72},
+ {w = 32, h = 16})
+
+ vars.in_door =
+ (player_pos.x + ai.player.size.w - 4 > 112 and player_pos.x < 144) and
+ (player_pos.y + ai.player.size.h > 72 )
+
+ end
+ vars.in_stairs = (player_pos.x < 48) and (player_pos.y < 18)
+ ui:updateMenuItem("up arrow", 1, {
+ x = map_pos.x + 17, y = map_pos.y + 5
+ })
+
+
+ nyq.map.set(0, ai.map.position)
+ nyq.world.update(0, ui.scale * ai.map.scaler)
+ ai.player.move = nil
+
+ -- map:update()
+ if vars.traverse_stairs then
+ if params.world_id == 1 then
+ print("going to world 2")
+ -- ui:changeMap(2, "spritesheet_indoors_1.png")
+ ui:changeMap{
+ id = 2,
+ world = "test",
+ spritesheet = "spritesheet_indoors_1.png"
+ }
+ elseif params.world_id == 2 then
+ print("going to world 1")
+ ui:changeMap{
+ id = 1,
+ world = "test",
+ spritesheet = "spritesheet_indoors_1.png",
+ }
+ end
+ end
+ if vars.go_outside then
+ ui:changeMap{
+ id = 3,
+ world = "test",
+ spritesheet = "spritesheet_outdoor_1.png",
+ outdoor = true,
+ }
+ end
+end
+
+function ui:pauseUpdate()
+ ui:imageUpdate(vars.start_menu.id,
+ vars.start_menu.position, vars.start_menu.size)
+ local size = ui:getTextSize2(vars.start_menu.selection[vars.selected], "id")
+ local text_pos = vars.start_menu.selection[vars.selected].position
+ ui:rectUpdate(vars.selection_rect,
+ {x = (vars.start_menu.position.x) + (4),
+ y = (text_pos.y)},
+ {w = (vars.start_menu.size.w) - (9),
+ h = size.h})
+ for i, selection in ipairs(vars.start_menu.selection) do
+ ui:updateText2(selection, "id", selection.position)
+ end
+end
+
+function ui:selectUpdate(options)
+ vars.selection_max = ui:optionSelectInit(options)
+ ui:optionSelectUpdate({x = 238, y = 118}, vars.selected)
+end
+
+function ui:textUpdate(text)
+ if vars.text_end then
+ vars.text_end = false
+ return
+ end
+
+ local lines = string.WordWrap(text, 38)
+ vars.text_max = math.ceil(#lines / 3)
+
+ for i = 1, 3 do
+ if not lines[i + (vars.text_pos * 3)] then
+ vars.text_done = true
+ break
+ end
+ local id = string.format("%d", i)
+ local y = 130 + ((i - 1) * (ui.font_size + 1))
+ ui:textChange("text", id, lines[i + (vars.text_pos * 3)],
+ {r = 255, g = 255, b = 255, a = 255},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+ ui:updateText("text", id, {x = 54, y = y})
+ end
+
+ ui:spriteUpdateCrop(vars.face_sprite_id, "face", 1, {
+ x = 0, y = 130
+ })
+ ui:rectUpdate(vars.text_rect_id,
+ {
+ x = 50,
+ y = 130
+ },
+ {
+ w = 190,
+ h = 30
+ })
+end
+
+return ui
--- /dev/null
+return State:new(
+ function()
+ nyq.keypress.trigger = false;
+ if ui.vars.in_door then
+ if nyq.keypress.select then
+ ui.vars.go_outside = true
+ ui.vars.in_door = false
+ end
+ end
+ if ui.vars.in_stairs then
+ if nyq.keypress.select then
+ ui.vars.traverse_stairs = true
+ ui.vars.in_stairs = false
+ end
+ end
+
+ if (nyq.keypress.pause) then
+ state = states.world.pause
+ -- uis.world.paused = true
+ end
+ ui.ai:collisionUpdate()
+
+ if nyq.keypress.move_north then
+ ui.ai:travel("north")
+ elseif nyq.keypress.move_east then
+ ui.ai:travel("east")
+ elseif nyq.keypress.move_south then
+ ui.ai:travel("south")
+ elseif nyq.keypress.move_west then
+ ui.ai:travel("west")
+ end
+ end
+)
--- /dev/null
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 2.0.20">
+<title>CLONEMON</title>
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
+<style>
+/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
+/* Uncomment the following line when using as a custom stylesheet */
+/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
+html{font-family:sans-serif;-webkit-text-size-adjust:100%}
+a{background:none}
+a:focus{outline:thin dotted}
+a:active,a:hover{outline:0}
+h1{font-size:2em;margin:.67em 0}
+b,strong{font-weight:bold}
+abbr{font-size:.9em}
+abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
+dfn{font-style:italic}
+hr{height:0}
+mark{background:#ff0;color:#000}
+code,kbd,pre,samp{font-family:monospace;font-size:1em}
+pre{white-space:pre-wrap}
+q{quotes:"\201C" "\201D" "\2018" "\2019"}
+small{font-size:80%}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
+sup{top:-.5em}
+sub{bottom:-.25em}
+img{border:0}
+svg:not(:root){overflow:hidden}
+figure{margin:0}
+audio,video{display:inline-block}
+audio:not([controls]){display:none;height:0}
+fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
+legend{border:0;padding:0}
+button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
+button,input{line-height:normal}
+button,select{text-transform:none}
+button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
+button[disabled],html input[disabled]{cursor:default}
+input[type=checkbox],input[type=radio]{padding:0}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
+textarea{overflow:auto;vertical-align:top}
+table{border-collapse:collapse;border-spacing:0}
+*,::before,::after{box-sizing:border-box}
+html,body{font-size:100%}
+body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
+a:hover{cursor:pointer}
+img,object,embed{max-width:100%;height:auto}
+object,embed{height:100%}
+img{-ms-interpolation-mode:bicubic}
+.left{float:left!important}
+.right{float:right!important}
+.text-left{text-align:left!important}
+.text-right{text-align:right!important}
+.text-center{text-align:center!important}
+.text-justify{text-align:justify!important}
+.hide{display:none}
+img,object,svg{display:inline-block;vertical-align:middle}
+textarea{height:auto;min-height:50px}
+select{width:100%}
+.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
+div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
+a{color:#2156a5;text-decoration:underline;line-height:inherit}
+a:hover,a:focus{color:#1d4b8f}
+a img{border:0}
+p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
+p aside{font-size:.875em;line-height:1.35;font-style:italic}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
+h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
+h1{font-size:2.125em}
+h2{font-size:1.6875em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
+h4,h5{font-size:1.125em}
+h6{font-size:1em}
+hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
+em,i{font-style:italic;line-height:inherit}
+strong,b{font-weight:bold;line-height:inherit}
+small{font-size:60%;line-height:inherit}
+code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
+ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
+ul,ol{margin-left:1.5em}
+ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
+ul.circle{list-style-type:circle}
+ul.disc{list-style-type:disc}
+ul.square{list-style-type:square}
+ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
+ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
+dl dt{margin-bottom:.3125em;font-weight:bold}
+dl dd{margin-bottom:1.25em}
+blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
+blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
+@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
+h1{font-size:2.75em}
+h2{font-size:2.3125em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
+h4{font-size:1.4375em}}
+table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
+table thead,table tfoot{background:#f7f8f7}
+table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
+table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
+table tr.even,table tr.alt{background:#f8f8f7}
+table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
+h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
+.center{margin-left:auto;margin-right:auto}
+.stretch{width:100%}
+.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
+.clearfix::after,.float-group::after{clear:both}
+:not(pre).nobreak{word-wrap:normal}
+:not(pre).nowrap{white-space:nowrap}
+:not(pre).pre-wrap{white-space:pre-wrap}
+:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
+pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
+pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
+pre>code{display:block}
+pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
+em em{font-style:normal}
+strong strong{font-weight:400}
+.keyseq{color:rgba(51,51,51,.8)}
+kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
+.keyseq kbd:first-child{margin-left:0}
+.keyseq kbd:last-child{margin-right:0}
+.menuseq,.menuref{color:#000}
+.menuseq b:not(.caret),.menuref{font-weight:inherit}
+.menuseq{word-spacing:-.02em}
+.menuseq b.caret{font-size:1.25em;line-height:.8}
+.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
+b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
+b.button::before{content:"[";padding:0 3px 0 2px}
+b.button::after{content:"]";padding:0 2px 0 3px}
+p a>code:hover{color:rgba(0,0,0,.9)}
+#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
+#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
+#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
+#content{margin-top:1.25em}
+#content::before{content:none}
+#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
+#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
+#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
+#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
+#header .details span:first-child{margin-left:-.125em}
+#header .details span.email a{color:rgba(0,0,0,.85)}
+#header .details br{display:none}
+#header .details br+span::before{content:"\00a0\2013\00a0"}
+#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
+#header .details br+span#revremark::before{content:"\00a0|\00a0"}
+#header #revnumber{text-transform:capitalize}
+#header #revnumber::after{content:"\00a0"}
+#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
+#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
+#toc>ul{margin-left:.125em}
+#toc ul.sectlevel0>li>a{font-style:italic}
+#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
+#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
+#toc li{line-height:1.3334;margin-top:.3334em}
+#toc a{text-decoration:none}
+#toc a:active{text-decoration:underline}
+#toctitle{color:#7a2518;font-size:1.2em}
+@media screen and (min-width:768px){#toctitle{font-size:1.375em}
+body.toc2{padding-left:15em;padding-right:0}
+#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
+#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
+#toc.toc2>ul{font-size:.9em;margin-bottom:0}
+#toc.toc2 ul ul{margin-left:0;padding-left:1em}
+#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
+body.toc2.toc-right{padding-left:0;padding-right:15em}
+body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
+@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
+#toc.toc2{width:20em}
+#toc.toc2 #toctitle{font-size:1.375em}
+#toc.toc2>ul{font-size:.95em}
+#toc.toc2 ul ul{padding-left:1.25em}
+body.toc2.toc-right{padding-left:0;padding-right:20em}}
+#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
+#content #toc>:first-child{margin-top:0}
+#content #toc>:last-child{margin-bottom:0}
+#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
+#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
+#content{margin-bottom:.625em}
+.sect1{padding-bottom:.625em}
+@media screen and (min-width:768px){#content{margin-bottom:1.25em}
+.sect1{padding-bottom:1.25em}}
+.sect1:last-child{padding-bottom:0}
+.sect1+.sect1{border-top:1px solid #e7e7e9}
+#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
+#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
+#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
+#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
+#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
+details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
+details{margin-left:1.25rem}
+details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
+details>summary::-webkit-details-marker{display:none}
+details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
+details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
+details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
+.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
+table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
+.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
+.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
+.admonitionblock>table td.icon{text-align:center;width:80px}
+.admonitionblock>table td.icon img{max-width:none}
+.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
+.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
+.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
+.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
+.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
+.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
+.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
+.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
+.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
+@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
+@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
+.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
+.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
+.listingblock>.content{position:relative}
+.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
+.listingblock:hover code[data-lang]::before{display:block}
+.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
+.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
+.listingblock pre.highlightjs{padding:0}
+.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
+.listingblock pre.prettyprint{border-width:0}
+.prettyprint{background:#f7f7f8}
+pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
+pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
+pre.prettyprint li code[data-lang]::before{opacity:1}
+pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
+table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
+table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
+table.linenotable td.code{padding-left:.75em}
+table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
+pre.pygments span.linenos{display:inline-block;margin-right:.75em}
+.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
+.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
+.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
+.quoteblock blockquote{margin:0;padding:0;border:0}
+.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
+.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
+.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
+.verseblock{margin:0 1em 1.25em}
+.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
+.verseblock pre strong{font-weight:400}
+.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
+.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
+.quoteblock .attribution br,.verseblock .attribution br{display:none}
+.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
+.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
+.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
+.quoteblock.abstract{margin:0 1em 1.25em;display:block}
+.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
+.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
+.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
+.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
+.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
+p.tableblock:last-child{margin-bottom:0}
+td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
+td.tableblock>.content>:last-child{margin-bottom:-1.25em}
+table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
+table.grid-all>*>tr>*{border-width:1px}
+table.grid-cols>*>tr>*{border-width:0 1px}
+table.grid-rows>*>tr>*{border-width:1px 0}
+table.frame-all{border-width:1px}
+table.frame-ends{border-width:1px 0}
+table.frame-sides{border-width:0 1px}
+table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
+table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
+table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
+table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
+table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
+th.halign-left,td.halign-left{text-align:left}
+th.halign-right,td.halign-right{text-align:right}
+th.halign-center,td.halign-center{text-align:center}
+th.valign-top,td.valign-top{vertical-align:top}
+th.valign-bottom,td.valign-bottom{vertical-align:bottom}
+th.valign-middle,td.valign-middle{vertical-align:middle}
+table thead th,table tfoot th{font-weight:bold}
+tbody tr th{background:#f7f8f7}
+tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
+p.tableblock>code:only-child{background:none;padding:0}
+p.tableblock{font-size:1em}
+ol{margin-left:1.75em}
+ul li ol{margin-left:1.5em}
+dl dd{margin-left:1.125em}
+dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
+li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
+ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
+ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
+ul.unstyled,ol.unstyled{margin-left:0}
+li>p:empty:only-child::before{content:"";display:inline-block}
+ul.checklist>li>p:first-child{margin-left:-1em}
+ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
+ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
+ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
+ul.inline>li{margin-left:1.25em}
+.unstyled dl dt{font-weight:400;font-style:normal}
+ol.arabic{list-style-type:decimal}
+ol.decimal{list-style-type:decimal-leading-zero}
+ol.loweralpha{list-style-type:lower-alpha}
+ol.upperalpha{list-style-type:upper-alpha}
+ol.lowerroman{list-style-type:lower-roman}
+ol.upperroman{list-style-type:upper-roman}
+ol.lowergreek{list-style-type:lower-greek}
+.hdlist>table,.colist>table{border:0;background:none}
+.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
+td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
+td.hdlist1{font-weight:bold;padding-bottom:1.25em}
+td.hdlist2{word-wrap:anywhere}
+.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
+.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
+.colist td:not([class]):first-child img{max-width:none}
+.colist td:not([class]):last-child{padding:.25em 0}
+.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
+.imageblock.left{margin:.25em .625em 1.25em 0}
+.imageblock.right{margin:.25em 0 1.25em .625em}
+.imageblock>.title{margin-bottom:0}
+.imageblock.thumb,.imageblock.th{border-width:6px}
+.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
+.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
+.image.left{margin-right:.625em}
+.image.right{margin-left:.625em}
+a.image{text-decoration:none;display:inline-block}
+a.image object{pointer-events:none}
+sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
+sup.footnote a,sup.footnoteref a{text-decoration:none}
+sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
+#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
+#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
+#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
+#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
+#footnotes .footnote:last-of-type{margin-bottom:0}
+#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
+div.unbreakable{page-break-inside:avoid}
+.big{font-size:larger}
+.small{font-size:smaller}
+.underline{text-decoration:underline}
+.overline{text-decoration:overline}
+.line-through{text-decoration:line-through}
+.aqua{color:#00bfbf}
+.aqua-background{background:#00fafa}
+.black{color:#000}
+.black-background{background:#000}
+.blue{color:#0000bf}
+.blue-background{background:#0000fa}
+.fuchsia{color:#bf00bf}
+.fuchsia-background{background:#fa00fa}
+.gray{color:#606060}
+.gray-background{background:#7d7d7d}
+.green{color:#006000}
+.green-background{background:#007d00}
+.lime{color:#00bf00}
+.lime-background{background:#00fa00}
+.maroon{color:#600000}
+.maroon-background{background:#7d0000}
+.navy{color:#000060}
+.navy-background{background:#00007d}
+.olive{color:#606000}
+.olive-background{background:#7d7d00}
+.purple{color:#600060}
+.purple-background{background:#7d007d}
+.red{color:#bf0000}
+.red-background{background:#fa0000}
+.silver{color:#909090}
+.silver-background{background:#bcbcbc}
+.teal{color:#006060}
+.teal-background{background:#007d7d}
+.white{color:#bfbfbf}
+.white-background{background:#fafafa}
+.yellow{color:#bfbf00}
+.yellow-background{background:#fafa00}
+span.icon>.fa{cursor:default}
+a span.icon>.fa{cursor:inherit}
+.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
+.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
+.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
+.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
+.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
+.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
+.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
+.conum[data-value] *{color:#fff!important}
+.conum[data-value]+b{display:none}
+.conum[data-value]::after{content:attr(data-value)}
+pre .conum[data-value]{position:relative;top:-.125em}
+b.conum *{color:inherit!important}
+.conum:not([data-value]):empty{display:none}
+dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
+h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
+p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
+p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
+p{margin-bottom:1.25rem}
+.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
+.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
+.print-only{display:none!important}
+@page{margin:1.25cm .75cm}
+@media print{*{box-shadow:none!important;text-shadow:none!important}
+html{font-size:80%}
+a{color:inherit!important;text-decoration:underline!important}
+a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
+a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
+abbr[title]{border-bottom:1px dotted}
+abbr[title]::after{content:" (" attr(title) ")"}
+pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
+thead{display:table-header-group}
+svg{max-width:100%}
+p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
+h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
+#header,#content,#footnotes,#footer{max-width:none}
+#toc,.sidebarblock,.exampleblock>.content{background:none!important}
+#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
+body.book #header{text-align:center}
+body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
+body.book #header .details{border:0!important;display:block;padding:0!important}
+body.book #header .details span:first-child{margin-left:0!important}
+body.book #header .details br{display:block}
+body.book #header .details br+span::before{content:none!important}
+body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
+body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
+.listingblock code[data-lang]::before{display:block}
+#footer{padding:0 .9375em}
+.hide-on-print{display:none!important}
+.print-only{display:block!important}
+.hide-for-print{display:none!important}
+.show-for-print{display:inherit!important}}
+@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
+.sect1{padding:0!important}
+.sect1+.sect1{border:0}
+#footer{background:none}
+#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
+@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
+</style>
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
+<head>
+<!-- <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=DotGothic16"> -->
+<!-- <link rel="icon" type="image/x-icon" href="https://raw.githubusercontent.com/A-Larsen/math-notes/refs/heads/main/favicon.png"> -->
+<!-- <link rel="icon" type="image/png" href="N2DE_favicon.png"/> -->
+<!-- <link rel="preconnect" href="https://fonts.googleapis.com"> -->
+<!-- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> -->
+<!-- <link href="https://fonts.googleapis.com/css2?family=Abril+Fatface&display=swap" rel="stylesheet"> -->
+<style>
+
+/*--------------------------------------------------------------*/
+/*use '!important' to override default css used by asciidoctor*/
+/*--------------------------------------------------------------*/
+
+:root {
+ --gruvbox-black: #282828;
+ --gruvbox-black2: #1d2021;
+ --gruvbox-black3: #463f39;
+ --gruvbox-red: #fc7869;
+ --gruvbox-yellow: #fabd2f;
+ --gruvbox-white: #ebdbb2;
+ --gruvbox-white2: #a7a187;
+ --gruvbox-blue: #83a598;
+ --gruvbox-green: #b8bb26;
+ --gruvbox-bg1: #7c6f64;
+ --gruvbox-bg2: #665c54;
+
+}
+
+.title {
+ color: var(--gruvbox-red) !important;
+}
+
+blockquote {
+ color: var(--gruvbox-white) !important;
+}
+
+table {
+ margin: 0 auto !important;
+}
+
+.hdlist1 {
+ font-size: 1.3em;
+}
+
+cite {
+ color: var(--gruvbox-green) !important;
+}
+
+.tableblock {
+ background-color: inherit;
+ color: var(--gruvbox-white);
+ max-width: 95%;
+}
+
+.tableblock th {
+ background-color: var(--gruvbox-black3);
+ color: var(--gruvbox-white);
+ max-width: 97%;
+}
+
+code:not([data-lang]) {
+ background-color: var(--gruvbox-bg2) !important;
+ color: var(--gruvbox-white);
+ text-shadow: none;
+}
+
+.checklist {
+ text-align: left;
+ font-size: .8em;
+}
+
+.checklist li ul { margin-left: 3%;
+}
+
+#content, h1, pre {
+ border-radius: 8px !important;
+}
+
+#header, #content, #footnotes, #footer {
+ padding-left: 0 !important;
+ padding-right: 0 !important;
+}
+
+.api-type a:hover {
+ text-decoration: underline;
+}
+
+.api-type, .api-type a {
+ color: var(--gruvbox-green);
+ text-decoration: none;
+}
+
+pre {
+ border-style: solid !important;
+ border-color: white !important;
+ border-width: 2px !important;
+}
+
+h1 {
+ /* font-family: "DotGothic16", sans-serif !important;*/
+
+
+ background-color: var(--gruvbox-white2) !important;
+ color: var(--gruvbox-black) !important;
+}
+
+.admonitionblock > table td.content {
+ color: var(--gruvbox-white) !important;
+}
+
+/*
+html {
+ margin: 0;
+ height: 100%;
+ width: 100%;
+}
+
+
+*/
+/*html {*/
+
+body {
+ /*background: black url("background-image-space.jpeg") no-repeat fixed center;*/
+ /*background-color: black;*/
+ background-color: var(--gruvbox-black);
+ background-attachment: fixed;
+ background-size: cover;
+ overflow-y: scroll;
+ /*
+ margin: 0;
+ height: 100%;
+ width: 100%;
+ overflow: hidden;
+ */
+}
+
+
+/*
+body {
+ overflow-y: scroll;
+ background: rgba(0,0,0,0);
+ height: 100%;
+ margin: 2%;
+}
+*/
+
+#toc {
+ background-color: var(--gruvbox-black2) !important;
+ /*opacity: .9;*/
+}
+
+#toctitle {
+ color: var(--gruvbox-yellow);
+}
+
+a {
+ color: var(--gruvbox-bg1);
+}
+
+#content {
+ color: #ebdbb2;
+ background: var(--gruvbox-black);
+ /*opacity: .9;*/
+}
+
+#header > h1:nth-last-child(2) {
+ border-bottom: none !important;
+ background-color: rgba(0, 0, 0, .1);
+ padding-left: 2%;
+}
+
+.sect1 + .sect1 {
+ border-top: none !important;
+}
+
+.sect1 h2 {
+ background-size: cover;
+ background-attachment: fixed;
+ /*
+ border-bottom: 1px solid var(--gruvbox-white);
+ border-top: 1px solid var(--gruvbox-white);
+ */
+ padding: 10px;
+ text-align: left;
+ color: var(--gruvbox-red) !important;
+ /*
+ text-shadow: 1px 1px 1px var(--gruvbox-black);
+ text-shadow: 3px 3px 3px var(--gruvbox-black);
+ text-shadow: 5px 5px 5px var(--gruvbox-blue);
+ */
+}
+
+h3, h4, h5 {
+ /*
+ text-shadow: 1px 1px 1px var(--gruvbox-white);
+ */
+}
+
+h3 {
+ color: var(--gruvbox-red) !important;
+}
+
+h4 {
+ color: var(--gruvbox-yellow) !important;
+}
+
+h5 {
+ color: #83a598 !important;
+}
+
+h2 ~ *:not(h1) {
+ margin-left: .5em;
+}
+
+.pygments {
+ max-width: 97% !important;
+ white-space: pre;
+ overflow-x: scroll !important;
+}
+
+::before {
+ /*makes sure that the programming language that show up on hover is within
+ pre tag*/
+ padding-right: 3%;
+}
+
+@media screen and (max-width: 800px) {
+ .checklist li ul {
+ margin-left: 6% !important;
+ }
+ #toc {
+ padding-left: 10px;
+ }
+
+ footer {
+ margin-bottom: 10px !important;
+ }
+ html {
+ margin-bottom: 10px !important;
+ }
+}
+@media screen and (max-width: 535px) {
+ h3 ~ *:not(h2):not(h3) {
+ margin-left: 0 !important;
+ }
+
+ h4 ~ *:not(h2):not(h3):not(.h3):not(h4) {
+ margin-left: 0 !important;
+ }
+ h5 ~ *:not(h2):not(h3):not(.h3):not(h4):not(.h4):not(h5) {
+ margin-left: 0 !important;
+ }
+
+ footer {
+ margin-bottom: 10px !important;
+ }
+ html {
+ margin-bottom: 10px !important;
+ }
+}
+h3 ~ *:not(h2):not(h3) {
+ margin-left: 1.5em;
+}
+
+h4 ~ *:not(h2):not(h3):not(.h3):not(h4) {
+ margin-left: 2em;
+}
+h5 ~ *:not(h2):not(h3):not(.h3):not(h4):not(.h4):not(h5) {
+ margin-left: 2.5em;
+}
+
+
+.sect1 h2 {
+
+ /*
+ background: linear-gradient(
+ to bottom,
+ rgba(251, 189, 47, 0.2), /* yellow */
+ rgba(0, 0, 0, 0.4) /* black */
+ );
+ */
+ /*opacity: .9;*/
+ }
+
+#preamble p{
+ padding-left: 10px;
+ color: var(--gruvbox-white) !important;
+}
+
+#footer {
+ max-width: 62.5em !important;
+ padding-left: 10px !important;
+ text-align: center;
+}
+
+.logo img {
+ display: block !important;
+ margin-left: auto !important;
+ margin-right: auto !important;
+}
+
+#header > h1:first-child {
+ margin-top: .3em !important;
+ padding-top: .2em !important;
+ text-align: center;
+}
+
+footer {
+ max-width: 62.5em;
+ margin-left: auto;
+ margin-right: auto;
+ display: block;
+
+}
+
+details[open] > summary::before {
+ /* display: none;*/
+ border-top: none;
+ content: "â–¼";
+ margin-top: -12px;
+}
+
+.example.stemblock {
+ border: solid;
+ font-size: 2vw;
+ max-width: 40%;
+ margin: auto;
+}
+
+.center {
+ max-width: 500px;
+ display: flex;
+ justify-content: center;
+}
+
+.highlight {
+ color: var(--gruvbox-yellow)
+}
+
+.border {
+ padding: 4px;
+ border: 2px solid rgba(255, 0, 0, .3);
+}
+
+.dull {
+ opacity: 40%;
+}
+
+.inline {
+ margin-right: 5%;
+ display: inline-block;
+}
+
+
+</style>
+
+</head>
+
+<script src="docinfo.js"></script>
+
+
+</head>
+<body class="article">
+<div id="header">
+<h1>CLONEMON</h1>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph">
+<p>Clonemon is a game I am working on that uses my custom game engine called the
+nyquist2DEngine. The source code for the game engine is not included in this
+repository.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_controls">Controls</h2>
+<div class="sectionbody">
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">key / keycombo</th>
+<th class="tableblock halign-left valign-top">control</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">enter/j</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">select</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">cntrl + ~</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">enter terminal</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">w</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">move up</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">a</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">move left</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">s</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">move down</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">d</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">move right</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">k</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">select up</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">h</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">select left</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">j</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">select down</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">l</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">select right</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">esc</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pause</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_terminal_commands">Terminal commands</h2>
+<div class="sectionbody">
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 50%;">
+<col style="width: 50%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">command</th>
+<th class="tableblock halign-left valign-top">action</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">c.bag()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">change to bag global state</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">c.world()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">chanage to world global state</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">c.enter_text()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">chanage to enter text global state</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">c.start()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">chanage to start global state</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">c.choice_select()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">chanage to choice select global state</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">c.loadsave()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">chanage to loadsave global state</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">c.party()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">chanage to party gobal state</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">c.battle()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">chanage to party gobal state</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">c.setState()</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">change to a substate ex. setState(states.battle.moveSelect)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">lua <command></p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">enter custom lua</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_terminal_substates">Terminal substates</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Every substate only works while running in the correct global state. For
+example any <code>states.battle</code> state only works in the battle global state.</p>
+</div>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 20%;">
+<col style="width: 80%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">substate</th>
+<th class="tableblock halign-left valign-top">action</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">states.battle.moveSelect</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">pick from your clonemons available moves</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">states.battle.doSelect</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">decide what your clonemon will do in battle</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">states.battle.enterBattle</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">starts the battle intro</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">states.party.doWhat</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">decide what you want to do with choosen clonemon</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">states.party.switch</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">switch clonemon to a different party slot</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_installation">Installation</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Put the binaries create from building the nyquist2DEnine engine or mapeditor in
+the root directory. The "*.so" or ".dll" files created from building the
+nyquist2DEngine extensions in the root of the extensions folder.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_running">Running</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>run these commands to initialize the game</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>./scripts/init
+./scripts/sourceme</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>you can do</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>./n2de_dev</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>or</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre>./n2de</pre>
+</div>
+</div>
+<div class="paragraph">
+<p>run run the game</p>
+</div>
+</div>
+</div>
+</div>
+<script type="text/x-mathjax-config">
+MathJax.Hub.Config({
+ messageStyle: "none",
+ tex2jax: {
+ inlineMath: [["\\(", "\\)"]],
+ displayMath: [["\\[", "\\]"]],
+ ignoreClass: "nostem|nolatexmath"
+ },
+ asciimath2jax: {
+ delimiters: [["\\$", "\\$"]],
+ ignoreClass: "nostem|noasciimath"
+ },
+ TeX: { equationNumbers: { autoNumber: "none" } }
+})
+MathJax.Hub.Register.StartupHook("AsciiMath Jax Ready", function () {
+ MathJax.InputJax.AsciiMath.postfilterHooks.Add(function (data, node) {
+ if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains("stemblock")) {
+ data.math.root.display = "block"
+ }
+ return data
+ })
+})
+</script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.9/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env bash
+
+function usage() {
+ # https://stackoverflow.com/questions/1835943/how-to-determine-function-name-from-inside-a-function
+ man "${0%/*}/man/bplate.1"
+}
+
+function new-ui() {
+
+local uis=()
+declare -A spritesheets
+declare -A states
+# local state="main"
+
+local ns=0
+for arg in $@; do
+ (( $# <= 0 ))&& break;
+ case $1 in
+ --ns)
+ ns=1
+ shift
+ ;;
+ --spritesheet)
+ spritesheets["$ui"]="$2"
+ shift 2
+ ;;
+
+ --state)
+ states["$ui"]="$2"
+ shift 2
+ ;;
+
+ *)
+ local ui=$1
+ uis+=("$1")
+ if ((ns == 0)); then
+ states["$1"]="main"
+ fi
+ ns=0
+ shift
+ ;;
+ esac
+
+done
+
+for ui in ${uis[@]}; do
+ if [[ -f ./uis/"${ui}.lua" ]] || [[ -d ./states/"${ui}" ]]; then
+ echo "ui ${ui} exists" >&2
+ echo "skipping this ui" >&2
+ continue
+ fi
+ local spritesheet="${spritesheets[$ui]}"
+ local state="${states[$ui]}"
+ [[ ! -v states[$ui] ]]; hasState=$?
+ if [[ -v spritesheets[$ui] ]]; then
+
+ cat > ./uis/"${ui}".lua << EOF
+local ui = {}
+
+function ui:init(spritesheet, window_size, options)
+ setmetatable(ui, require("extensions.metatables.ui"))
+ ui:_init(spritesheet, window_size, "NotoSansMono-Regular.ttf", 12, options, function()
+ end)
+end
+
+function ui:startCallback()
+end
+
+function ui:update()
+end
+
+return ui
+EOF
+else
+ cat > ./uis/"${ui}".lua << EOF
+local ui = {}
+
+function ui:init(window_size, options)
+ setmetatable(ui, require("extensions.metatables.ui"))
+ ui:_init(nil, window_size, "NotoSansMono-Regular.ttf", 12, options, function()
+ end)
+end
+
+function ui:startCallback()
+end
+
+function ui:update()
+end
+
+return ui
+EOF
+ fi
+ if ((hasState)); then
+ mkdir ./states/"${ui}"
+ cat > ./states/"${ui}"/init.lua << EOF
+return {
+ main = require("states.${ui}.${state}");
+}
+EOF
+ cat >> ./states/init.lua << EOF
+states.${ui} = require("states.${ui}")
+EOF
+
+ cat > ./states/"${ui}"/"${state}".lua << EOF
+return State:new(
+ function()
+ if nyq.keypress.back then
+ Pop_state()
+ end
+ end
+)
+EOF
+ fi
+
+ cat >> ./uis/init.lua << EOF
+uis.${ui} = require("uis.${ui}")
+EOF
+ matches=($(grep -nE "^uis.\w*:init(.*)" ./init.lua | cut -f1 -d:))
+ lastmatch="${matches[-1]}"
+
+ if [[ -v spritesheets[$ui] ]]; then
+ sed -i "${lastmatch}a\uis.${ui}:init(\"${spritesheet}\", unscaled_window_size, {scale = Ex.Config.resolution_scale})" ./init.lua
+ else
+ sed -i "${lastmatch}a\uis.${ui}:init(unscaled_window_size, {scale = Ex.Config.resolution_scale})" ./init.lua
+ fi
+done
+} # function end
+
+function new-state() {
+declare -A states
+
+for arg in $@; do
+ (( $# <= 0 )) && break;
+
+ case $1 in
+ --ui)
+ states["$2"]="$3"
+ shift 3
+ ;;
+ esac
+done
+
+for ui in ${!states[@]}; do
+ local state=${states[$ui]}
+ cat > ./states/"${ui}"/"${state}".lua << EOF
+return State:new(
+ function()
+ if nyq.keypress.back then
+ Pop_state()
+ end
+ end
+)
+EOF
+ matches=($(grep -nE "\s.*\w.*=" ./states/"${ui}"/init.lua | cut -f1 -d:))
+ lastmatch="${matches[-1]}"
+ sed -i "${lastmatch}a\ ${state} = require(\"states.${ui}.${state}\");" ./states/"${ui}"/init.lua
+done
+
+}
+
+function rm-state() {
+declare -A states
+
+for arg in $@; do
+ (( $# <= 0 )) && break;
+
+ case $1 in
+ --ui)
+ states["$2"]="$3"
+ shift 3
+ ;;
+ esac
+done
+
+for ui in ${!states[@]}; do
+ local state="${states[$ui]}"
+ sed -i "/${state} = require/d" ./states/${ui}/init.lua
+ rm -rf ./states/${ui}/${state}.lua
+done
+}
+
+function rm-ui() {
+local uis=()
+
+for arg in $@; do
+ uis+=("$arg")
+done
+
+for ui in ${uis[@]}; do
+ sed -i "/^uis.${ui}:init(.*)/d" ./init.lua
+ sed -i "/uis.${ui} = require(\"uis.${ui}\")/d" ./uis/init.lua
+ sed -i "/states.${ui} = require(\"states.${ui}\")/d" ./states/init.lua
+ rm -rf ./states/"${ui}" ./uis/"${ui}.lua"
+done
+}
+
+for args in $@; do
+ case $args in
+ new-ui)
+ shift
+ new-ui $@
+ exit
+ ;;
+ new-state)
+ shift
+ new-state $@
+ exit
+ ;;
+ rm-ui)
+ shift
+ rm-ui $@
+ exit
+ ;;
+ rm-state)
+ shift
+ rm-state $@
+ exit
+ ;;
+ -h|--help)
+ usage
+ exit
+ ;;
+ esac
+done
--- /dev/null
+#!/usr/bin/env bash
+for file in $(ls -1) do
+ echo $file
+end
--- /dev/null
+#!/usr/bin/env bash
+
+steam_dir="./steam/ContentBuilder/content/windows"
+[[ ! -d "$steam_dir" ]] && mkdir -p "$steam_dir"
+cd "$steam_dir" || exit
+folders=$(find . -maxdepth 1 -type d -not -name '.' -not -name '..')
+files=$(find . -maxdepth 1 -type f)
+
+rm -rf $folders
+rm -rf $files
--- /dev/null
+#!/usr/bin/env bash
+
+if [[ "$1" == "schema" ]]; then
+ if [[ ! -z "$2" ]]; then
+ sqlite3 ./resources/test.db ".schema" | grep $2
+ else
+ sqlite3 ./resources/test.db ".schema"
+ fi
+fi
--- /dev/null
+#!/usr/bin/env bash
+
+sqlite3 ./resources/test.db << EOF
+DELETE FROM clonemon_types;
+DELETE FROM clonemon;
+UPDATE sqlite_sequence SET seq = 0 WHERE name = "clonemon_types";
+UPDATE sqlite_sequence SET seq = 0 WHERE name = "clonemon";
+
+INSERT INTO clonemon_types (name, ability, base_attack, base_hp, base_speed,
+ base_defense, base_special_defense,
+ base_special_attack,
+ image)
+VALUES (
+-- name
+"thorp",
+
+-- ability
+"spam",
+
+-- base_attack
+100,
+
+-- base_hp
+25,
+
+-- base_speed
+10,
+
+-- base_defense
+50,
+
+-- base_special_defense
+50,
+
+-- base_special_attack
+50,
+
+-- image
+"spritesheet_thorp.png"
+),
+(
+-- name
+"shela",
+
+-- ability
+"throw",
+
+-- base_attack
+100,
+
+-- base_hp
+25,
+
+-- base_speed
+10,
+
+-- base_defense
+50,
+
+-- base_special_defense
+50,
+
+-- base_special_attack
+50,
+
+-- image
+"spritesheet_shela.png"
+);
+
+INSERT INTO clonemon (type_id, name, gender, level, attack, max_hp,
+ remaining_hp, speed, defense, accuracy, special_defense,
+ special_attack, box_number, box_position, spritesheet)
+VALUES (
+-- type_id
+1,
+
+-- name
+"thorper",
+
+-- gender
+0,
+
+-- level
+20,
+
+-- attack
+0,
+
+-- max_hp
+10,
+
+-- remaining_hp
+10,
+
+-- speed
+20,
+
+-- defense
+20,
+
+-- accuracy
+20,
+
+-- special_defense
+20,
+
+
+-- special_attack
+20,
+
+-- box_number
+1,
+
+-- box_position
+1,
+
+-- spritesheet
+"spritesheet_1.png"
+),
+(
+-- type_id
+2,
+
+-- name
+"shela",
+
+-- gender
+1,
+
+-- level
+22,
+
+-- attack
+0,
+
+-- max_hp
+10,
+
+-- remaining_hp
+10,
+
+-- speed
+20,
+
+-- defense
+20,
+
+-- accuracy
+20,
+
+-- special_defense
+20,
+
+-- special_attack
+20,
+
+-- box_number
+1,
+
+-- box_position
+2,
+
+--spritesheet
+"spritesheet_2.png");
+EOF
--- /dev/null
+#!/usr/bin/env bash
+#
+sqlite3 ./resources/test.db << EOF
+DELETE FROM people;
+DELETE FROM players;
+
+INSERT INTO people (age, name, level, spritesheet)
+VALUES (44, "joe", 18, "thing.png");
+
+INSERT INTO people (age, name, level, spritesheet)
+VALUES (100, "jim", 2, "something.png");
+
+INSERT INTO people (age, name, level, spritesheet)
+VALUES (1, "jam", 20, "nothing.png");
+
+INSERT INTO players(uuid, person_id)
+VALUES (1, 1);
+
+INSERT INTO players(uuid, person_id)
+VALUES (2, 2);
+
+INSERT INTO players(uuid, person_id)
+VALUES (3, 3);
+EOF
--- /dev/null
+#!wine ./n2de.exe
+local database = require("extensions.database")
+local config = require("config")
--- /dev/null
+#!/usr/bin/env bash
+
+[[ ! -d .cache/formats/ ]] && mkdir -p .cache/formats/
--- /dev/null
+.TH bplate "3" "January 2024" "Nyquist2DEngine 0.0.0.1" "User Commands"
+.SH NAME
+bplate \- helps create boilerplate for codebase
+.SH SYNOPSIS
+.B bplate
+.B rm-state
+.RB [ \--ui
+.IR ui
+.IR state ]
+\&...
+.PP
+.B bplate
+.B new-state
+.RB [ \--ui
+.IR ui
+.IR state ]
+\&...
+.PP
+.B bplate
+.B new-ui
+.RB [
+.RB [ \-\-ns ]
+.IR ui
+.RB [ \-\-spritesheet
+.IR spritesheet ]
+.RB [ \-\-state
+.IR state ]]
+\&...
+.PP
+.B bplate
+.B rm-ui
+.IR ui
+\&...
+.SH DESCRIPTION
+.TP
+.B new-ui
+.PP
+.in +3n
+create new ui(s) and and state for each ui called "main"
+you can also specify the state name with
+.B --state
+.in
+.TP
+.B rm-ui
+removes ui(s)
+.TP
+.B new-state
+creates new state(s)
+.TP
+.B rm-state
+removes state(s)
+.SH OPTIONS
+.NH
+.B
+new-ui
+.RS
+.TP
+.BI \-\-spritesheet " spritesheet"
+spritesheet to use for the ui
+.TP
+.BI \-\-state " state"
+specific the name of the first state to be created
+.RE
+.NH
+.B
+rm-state
+.NH
+.B
+new-state
+.RS
+.TP
+.BI \-\-ui " ui"
+specify ui to to add or remove a state from
+.RE
+.SH EXAMPLES
+create a ui "one" with spritesheet "sup", ui two with no spritesheet, ui three
+with spritesheet hey and then ui four with no spritesheet and no state
+.PP
+Ex.
+.in +5n
+.EX
+$ bplate new-ui one --spritesheet sup two three --spritesheet hey --ns four
+.EE
+.in
+.PP
+remove ui one two three and four and states that may be associated with them
+.PP
+Ex.
+.in +5n
+.EX
+$ bplate rm-ui one two three four
+.EE
+.in
+.SH AUTHOR
+.AU
+Written by Austin Michael Larsen to work with the nyquist2DEngine
--- /dev/null
+#!/usr/bin/env sh
+
+sqlite3 ./resources/test.db <<EOF
+UPDATE keyboard_mappings SET
+ move_north = "W",
+ move_east = "D",
+ move_south = "S",
+ move_west = "A",
+ move_up = "K",
+ move_right = "L",
+ move_down = "J",
+ move_left = "H",
+ _select = "Return",
+ back = "P",
+ pause = "Tab",
+ hotkey = "X"
+WHERE id = 1;
+
+UPDATE config SET
+ controller = "none",
+ fullscreen = 0,
+ resolution_scale = 5,
+ speed = 7
+WHERE id = 1;
+.print "finished"
+EOF
+
--- /dev/null
+#!/usr/bin/env bash
+#
+cd ./steam/ContentBuilder/scripts/
+steamcmd +login "${1}" +quit
+sed -i "4s/.*/ \"Desc\" \"${2}\"/" ./app_build_2762580.vdf
+steamcmd +runscript << EOF
+login "$1"
+run_app_build $PWD/app_build_2762580.vdf
+quit
+EOF
--- /dev/null
+#!/usr/bin/env bash
+
+rm -rf "./resources/test.db"
+
+windows_dir=./steam/ContentBuilder/content/windows
+steamdeck_dir=./steam/ContentBuilder/content/steamdeck
+
+folder_ignore=('steam' 'scripts' 'docs' '.git' 'old')
+file_ignore=('.gitignore' "n2de_dev.exe")
+
+folder_strings=()
+file_strings=()
+
+for a in ${folder_ignore[@]}; do
+ folder_strings+=("-not -name $a")
+done
+
+for b in ${file_ignore[@]}; do
+ file_strings+=("-not -name $b")
+done
+
+# folders=$(find . -maxdepth 1 -type d ${folder_strings[@]} -not -name '.' -not -name '..')
+# files=$(find . -maxdepth 1 -type f ${file_strings[@]} -not -name '.' -not -name '..')
+
+folders=($(find . -maxdepth 1 -type d ${folder_strings[@]} -not -name '.' -not -name '..'))
+files=($(find . -maxdepth 1 -type f ${file_strings[@]} -not -name '.' -not -name '..'))
+
+# cp -r $folders $files $steamdeck_dir
+
+# cp -r $folders $files $windows_dir
+
+for file in ${files[@]}; do
+ if [[ "$file" =~ .lua$ ]]; then
+ luac5.4 -o $windows_dir/$file $file
+ else
+ cp $file $windows_dir
+ fi
+done
+
+for folder in ${folders[@]}; do
+ # echo $folder
+ files=($(find $folder -type f))
+ for file in ${files[@]}; do
+ path="${windows_dir}$(echo ${file%/*} | cut -b 2-)"
+ if [[ $file =~ .lua$ ]]; then
+
+ [[ ! -d "$path" ]] && mkdir -p "$path"
+ luac5.4 -o "${path}/${file##*/}" "$file"
+ else
+ [[ ! -d "$path" ]] && mkdir -p "$path"
+ cp "$file" "$path"
+ fi
+ done
+done
--- /dev/null
+#!wine ./n2de.exe
+os.remove("./resources/test.db")
+require("extensions")
--- /dev/null
+#!/usr/bin/env bash
+grep -R --include "*.lua" "\<$1\>"
--- /dev/null
+#!/usr/bin/env zsh
+export WINEDLLOVERRIDES="*d3d9,*d3d10,*d3d10_1,*d3d10core,*d3d11,*dxgi=b"
--- /dev/null
+#!/usr/bin/env zsh
+alias git="git.exe"
+alias make="make.exe"
+alias gdb="gdb.exe"
--- /dev/null
+return {
+ main = require("states.bag.main");
+}
--- /dev/null
+return State:new(
+ function()
+ if nyq.keypress.back then
+ Pop_state()
+ end
+ if nyq.keypress.move_right then
+ ui.vars.type_selected = (ui.vars.type_selected % ui.vars.type_section_max) + 1
+ ui.vars.selected = 1
+ elseif nyq.keypress.move_left then
+ ui.vars.type_selected = ((ui.vars.type_selected - 1) % ui.vars.type_section_max)
+ if ui.vars.type_selected == 0 then
+ ui.vars.type_selected = ui.vars.type_section_max
+ end
+ ui.vars.selected = 1
+ elseif nyq.keypress.move_down and ui.vars.selected < ui.vars.selection_max then
+ ui.vars.selected = ui.vars.selected + 1
+ elseif nyq.keypress.move_up and ui.vars.selected > 1 then
+ ui.vars.selected = ui.vars.selected - 1
+ end
+ end
+)
--- /dev/null
+return State:new(
+ function()
+ if (nyq.keypress.select) then
+ -- terminal.commands.world()
+ -- Pop_state()
+ if ui.vars.selected == 1 then
+ Push_state()
+ state = states.battle.moveSelect
+ elseif ui.vars.selected == 2 then
+ Push_state()
+ states.bag.main:reset()
+ state = states.bag.main
+ temps.ui = uis.bag
+ params = {
+ items = {
+ [1] = {
+ name = "book",
+ description = "can read it",
+ image = "",
+ quantity = 1
+ },
+ [2] = {
+ name = "cup",
+ description = "drink things",
+ image = "",
+ quantity = 2
+ },
+ [3] = {
+ name = "pencil",
+ description = "write things",
+ image = "",
+ quantity = 3
+ }
+ },
+ berries = {
+ [1] = {
+ name = "blueberry",
+ description = "improves stats",
+ image = "",
+ quantity = 1
+ },
+ [2] = {
+ name = "raseberry",
+ description = "raises defense stat",
+ image = "",
+ quantity = 2
+ },
+ [3] = {
+ name = "blackberry",
+ description = "clears status effects",
+ image = "",
+ quantity = 3
+ }
+ },
+ cloneballs = {
+ [1] = {
+ name = "ULTRA BALL",
+ description = "A better Ball with a higher catch rate than a Great Ball",
+ image = "",
+ quantity = 1
+ },
+ [2] = {
+ name = "NET BALL",
+ description = "A BALL that works on WATER- and BUG- type Clonemon",
+ image = "",
+ quantity = 2
+ },
+ }
+ }
+ elseif ui.vars.selected == 3 then
+ Push_state()
+ states.party.main:reset()
+ params = {
+ my_clonemon = my_clonemon
+ }
+ state = states.party.main
+ temps.ui = uis.party
+ end
+ elseif (nyq.keypress.back) then
+ -- terminal.commands.world()
+ Pop_state()
+ elseif (nyq.keypress.move_right) then
+ if (ui.vars.selected + 1 <= 4) then
+ ui.vars.selected = ui.vars.selected + 1
+ end
+ elseif (nyq.keypress.move_left) then
+ if (ui.vars.selected - 1 > 0) then
+ ui.vars.selected = ui.vars.selected - 1
+ end
+ elseif (nyq.keypress.move_down) then
+ if (ui.vars.selected + 2 <= 4) then
+ ui.vars.selected = ui.vars.selected + 2
+ end
+ elseif (nyq.keypress.move_up) then
+ if (ui.vars.selected - 2 > 0) then
+ ui.vars.selected = ui.vars.selected - 2
+ end
+ end
+
+ end
+
+)
--- /dev/null
+return State:new(function()
+ if ui.lines.narration.pages > 1 then
+ if nyq.keypress.select and ui.lines.narration.page_idx < ui.lines.narration.pages then
+ ui.lines.narration.page_idx = ui.lines.narration.page_idx + 1
+ end
+ else
+ if nyq.keypress.select then
+ state = states.battle.doSelect
+ end
+ end
+end)
--- /dev/null
+return {
+ moveSelect = require("states.battle.moveSelect");
+ enterBattle = require("states.battle.enterBattle");
+ doSelect = require("states.battle.doSelect");
+}
--- /dev/null
+return State:new(
+ function()
+ if (nyq.keypress.back) then
+ -- terminal.commands.world()
+ Pop_state()
+ elseif (nyq.keypress.move_right) then
+ if (ui.vars.selected + 1 <= 4) then
+ ui.vars.selected = ui.vars.selected + 1
+ end
+ elseif (nyq.keypress.move_left) then
+ if (ui.vars.selected - 1 > 0) then
+ ui.vars.selected = ui.vars.selected - 1
+ end
+ elseif (nyq.keypress.move_down) then
+ if (ui.vars.selected + 2 <= 4) then
+ ui.vars.selected = ui.vars.selected + 2
+ end
+ elseif (nyq.keypress.move_up) then
+ if (ui.vars.selected - 2 > 0) then
+ ui.vars.selected = ui.vars.selected - 2
+ end
+ -- elseif (nyq.keypress.change_moves1) then
+ -- -- battle_ui:addMoves(moves["pikachu"])
+ -- elseif (nyq.keypress.change_moves2) then
+ -- -- battle_ui:addMoves(moves["charzard"])
+ end
+
+ end
+
+)
--- /dev/null
+return {
+ main = require("states.choice_select.main")
+}
--- /dev/null
+return State:new(
+ function()
+ if nyq.keypress.move_right and ui.vars.selected < ui.vars.max then
+ ui.vars.selected = ui.vars.selected + 1
+ elseif nyq.keypress.move_left and ui.vars.selected > 1 then
+ ui.vars.selected = ui.vars.selected - 1
+ elseif nyq.keypress.select then
+ print(ui.vars.selected)
+ end
+ end
+)
--- /dev/null
+return {
+ main = require("states.enter_text.main")
+}
--- /dev/null
+return State:new(
+ function()
+ if ui.vars.string == nil then return end
+ local canInput = not ui.vars.full and string.len(ui.vars.string) < ui.vars.character_limit
+
+ if Ex.Config.controller ~= "none" then
+ if nyq.keypress.move_right and ui.vars.cursor <= 31 then
+ ui.vars.cursor = ui.vars.cursor + 1
+ elseif nyq.keypress.move_left and ui.vars.cursor > 0 then
+ if ui.vars.cursor == 32 then
+ ui.vars.cursor = ui.vars.cursor - 2
+ else
+ ui.vars.cursor = ui.vars.cursor - 1
+ end
+ elseif nyq.keypress.move_down and ui.vars.cursor < 22 then
+ ui.vars.cursor = ui.vars.cursor + 11
+ elseif nyq.keypress.move_up and ui.vars.cursor >= 11 then
+ ui.vars.cursor = ui.vars.cursor - 11
+ elseif nyq.keypress.back then
+ ui.vars.string = string.sub(ui.vars.string, 1, string.len(ui.vars.string) - 1)
+ elseif nyq.keypress.bag then
+ ui.vars.isUpper = not ui.vars.isUpper
+ elseif nyq.keypress.hotkey then
+ Pop_state()
+ -- terminal.commands.world()
+ end
+
+ local letter = ui.vars.letter_selection[ui.vars.cursor + 1]
+ if nyq.keypress.select then
+ if canInput and letter:match("[%a ]") then
+ if ui.vars.isUpper then
+ ui.vars.string = ui.vars.string .. string.upper(letter)
+ else
+ ui.vars.string = ui.vars.string .. letter
+ end
+ elseif letter == ui.vars.key_backspace then
+ ui.vars.string = string.sub(ui.vars.string, 1, string.len(ui.vars.string) - 1)
+ elseif letter == ui.vars.key_change_case then
+ ui.vars.isUpper = not ui.vars.isUpper
+ elseif letter == ui.vars.key_done then
+ -- terminal.commands.world()
+ Pop_state()
+ end
+ end
+ -- print(ui.cursor)
+ else
+ if nyq.keypress.select then
+ -- terminal.commands.world()
+ Pop_state()
+ end
+ end
+
+ nyq.keypress.trigger = true;
+
+ if nyq.key then
+ if nyq.key == '\b' then
+ -- if string.len(uis.enter_text.string) > 0 then
+ if string.len(ui.vars.string) > 0 then
+ -- ui.vars.string = string.sub(uis.enter_text.string, 1, string.len(ui.vars.string) - 1)
+ ui.vars.string = string.sub(ui.vars.string, 1, string.len(ui.vars.string) - 1)
+ end
+ if uis.enter_text.full then
+ ui.vars.full = false
+ end
+ else
+ if canInput then
+ ui.vars.string = ui.vars.string .. nyq.key
+ end
+ end
+ end
+ end
+)
--- /dev/null
+states = {}
+states.battle = require("states.battle")
+states.world = require("states.world")
+states.choice_select = require("states.choice_select")
+states.start = require("states.start")
+states.loadsave = require("states.loadsave")
+states.enter_text = require("states.enter_text")
+states.bag = require("states.bag")
+states.party = require("states.party")
+states.start_menu = require("states.start_menu")
+states.settings = require("states.settings")
+states.mapping = require("states.mapping")
+states.partybox = require("states.partybox")
--- /dev/null
+return {
+ main = require("states.loadsave.main");
+}
--- /dev/null
+return State:new(
+ function()
+ if nyq.keypress.select then
+ if #players == 0 then
+ print("go to player creation")
+ elseif ui.selected == 1 then
+ player = Ex.Database.getFromUUID("players", players[ui.selected2].uuid)
+ print("loading player:")
+ for k, v in pairs(player) do
+ print(k, v)
+ end
+ elseif ui.selected == 2 then
+ print("go to player creation")
+ end
+ local menu_items = {
+ [1] = { name = "Map", },
+ [2] = { name = "Clonemon", },
+ [3] = { name = "bag", },
+ [4] = { name = "Player", },
+ [5] = { name = "Save", },
+ [6] = { name = "Settings", },
+ [7] = { name = "Quit", }
+ }
+ params = {
+ menu_items = menu_items,
+ world_id = 1
+ }
+ temps.ui = uis.world
+ state = states.world.main
+ end
+ if #players > 0 then
+ if (nyq.keypress.move_down) then
+ if (ui.selected + 1 <= ui.menu_size) then
+ ui.selected = ui.selected + 1
+ end
+ elseif (nyq.keypress.move_up) then
+ if (ui.selected - 1 > 0) then
+ ui.selected = ui.selected - 1
+ end
+ elseif (nyq.keypress.move_right) then
+ if (ui.selected2 + 1 <= #players) then
+ ui.selected2 = ui.selected2 + 1
+ end
+ elseif (nyq.keypress.move_left) then
+ if (ui.selected2 - 1 > 0) then
+ ui.selected2 = ui.selected2 - 1
+ end
+ end
+ end
+ end
+)
+
--- /dev/null
+return {
+ main = require("states.mapping.main");
+}
--- /dev/null
+return State:new(
+ function ()
+
+ nyq.keypress.trigger = true;
+ local option = ui.vars.select_options[ui.vars.selected]
+
+
+ if ui.vars.state == "apply" then
+ print("applying?")
+ local mappings = ui.vars.temp_settings
+ for k, v in pairs(ui.vars.temp_settings) do
+ if v.key == "___" then
+ ui:notifySet("warning", "not all keys are mapped")
+ ui.vars.state = "select input"
+ ui.vars.isChangeingInput = false
+ return
+ end
+ end
+
+ Ex.Database.update(params.type .. "_mappings", 1, {
+ move_north = mappings.move_north.key,
+ move_east = mappings.move_east.key,
+ move_south = mappings.move_south.key,
+ move_west = mappings.move_west.key,
+ move_up = mappings.move_up.key,
+ move_right = mappings.move_right.key,
+ move_down = mappings.move_down.key,
+ move_left = mappings.move_left.key,
+ _select = mappings.select.key,
+ back = mappings.back.key,
+ pause = mappings.pause.key,
+ hotkey = mappings.hotkey.key,
+ })
+ ui:notifySet("change", "mappings have been applied")
+ ui.vars.state = "select input"
+ ui.vars.isChangeingInput = false
+ elseif ui.vars.state == "select input" then
+ if nyq.keypress.back then
+ Pop_state()
+ end
+ if nyq.keypress.select then
+ if option.value then
+ ui:setOptions(option.name)
+ ui.vars.isChangeingInput = true
+ ui.vars.state = "change input"
+ elseif option.name == "apply" then
+ ui.vars.isChangeingInput = true
+ ui.vars.state = "apply"
+ elseif option.name == "clear" then
+ for k, v in pairs(ui.vars.temp_settings) do
+ v.key = "___"
+ end
+ ui:setOptions()
+ elseif option.name == "go back" then
+ Pop_state()
+ end
+ elseif nyq.keypress.move_down and (ui.vars.selected + 1 <= ui.vars.selection_max) then
+ ui.vars.selected = ui.vars.selected + 1
+ elseif nyq.keypress.move_up and (ui.vars.selected - 1 > 0) then
+ ui.vars.selected = ui.vars.selected - 1
+ end
+ elseif ui.vars.state == "change input" then
+ nyq.delay(10)
+ local key = nil
+
+ if (params.type == "keyboard") then
+ key = nyq.keypressCheck()
+ elseif (params.type == "gamepad") then
+ key = nyq.gamepadCheck(0)
+ end
+
+
+ nyq.delay(10)
+ if key then
+ -- print(option.name, ui.temp_settings[option.name].key, key)
+ local found = false
+ for k, v in pairs(ui.vars.temp_settings) do
+ if
+ ((v.key == key) and
+ (not
+ (
+ (
+ (key:find("up") and option.name:find("north")) or
+ (key:find("right") and option.name:find("east")) or
+ (key:find("down") and option.name:find("south")) or
+ (key:find("left") and option.name:find("west"))
+ )
+ or
+ (
+ (key:find("up") and option.name:find("up")) or
+ (key:find("right") and option.name:find("right")) or
+ (key:find("down") and option.name:find("down")) or
+ (key:find("left") and option.name:find("left"))
+ )
+ )
+ )
+ ) and
+ (k ~= option.name)
+ then
+ found = true
+ break
+ end
+ end
+ if not found then
+ ui.vars.temp_settings[option.name].key = key
+ else
+ ui:notifySet("warning", "this key has already been mapped")
+ end
+ end
+ ui:setOptions()
+ ui.vars.state = "select input"
+ ui.vars.isChangeingInput = false
+ end
+
+ end
+)
--- /dev/null
+return State:new(
+ function()
+ if (nyq.keypress.select) then
+ if ui.vars.selected == ui:getSelectOptions()["Switch"] then
+ ui.vars.clonemon_switch = ui.vars.clonemon_selected
+ state = states.party.switch
+ end
+ elseif (nyq.keypress.back) then
+ ui.vars.selected = ui.vars.clonemon_selected
+ Pop_state()
+ elseif (nyq.keypress.move_down) and ui.vars.selected < ui.vars.selection_max then
+ ui.vars.selected = ui.vars.selected + 1
+ elseif (nyq.keypress.move_up) and ui.vars.selected > 1 then
+ ui.vars.selected = ui.vars.selected - 1
+ end
+
+ end
+
+)
--- /dev/null
+return {
+ main = require("states.party.main");
+ doWhat = require("states.party.doWhat");
+ switch = require("states.party.switch");
+}
--- /dev/null
+return State:new(
+ function()
+ if (nyq.keypress.select) and ui.vars.selected ~= 7 then
+ Push_state()
+ ui.vars.clonemon_selected = ui.vars.selected
+ ui.vars.selected = 1
+ state = states.party.doWhat
+ elseif (nyq.keypress.select) and ui.vars.selected == 7 then
+ Pop_state()
+ elseif (nyq.keypress.back) then
+ -- terminal.commands.world()
+ Pop_state()
+ elseif (nyq.keypress.move_right) then
+ if ui.vars.selected == 6 then
+ ui.vars.selected = 7
+ elseif (ui.vars.selected + 1 <= 6) then
+ ui.vars.selected = ui.vars.selected + 1
+ end
+ elseif (nyq.keypress.move_left) then
+ if (ui.vars.selected - 1 > 0) then
+ ui.vars.selected = ui.vars.selected - 1
+ end
+ elseif (nyq.keypress.move_down) then
+ if ui.vars.selected == 5 or ui.vars.selected == 6 then
+ ui.vars.selected = 7
+ elseif (ui.vars.selected + 2 <= 6) then
+ ui.vars.selected = ui.vars.selected + 2
+ end
+ elseif (nyq.keypress.move_up) then
+ if ui.vars.selected == 7 then
+ ui.vars.selected = 6
+ elseif (ui.vars.selected - 2 > 0) then
+ ui.vars.selected = ui.vars.selected - 2
+ end
+ end
+
+ end
+
+)
--- /dev/null
+return State:new(
+ function()
+ if (nyq.keypress.select) then
+ local temp = my_clonemon[ui.vars.clonemon_selected]
+ my_clonemon[ui.vars.clonemon_selected] = my_clonemon[ui.vars.clonemon_switch]
+ my_clonemon[ui.vars.clonemon_switch] = temp
+ params.my_clonemon = my_clonemon
+ ui.vars.selected = ui.vars.clonemon_switch
+ Pop_state()
+
+ elseif (nyq.keypress.back) then
+ Pop_state()
+ elseif (nyq.keypress.move_right) then
+ if (ui.vars.clonemon_switch + 1 <= 6) then
+ ui.vars.clonemon_switch = ui.vars.clonemon_switch + 1
+ end
+ elseif (nyq.keypress.move_left) then
+ if (ui.vars.clonemon_switch - 1 > 0) then
+ ui.vars.clonemon_switch = ui.vars.clonemon_switch - 1
+ end
+ elseif (nyq.keypress.move_down) then
+ if (ui.vars.clonemon_switch + 2 <= 6) then
+ ui.vars.clonemon_switch = ui.vars.clonemon_switch + 2
+ end
+ elseif (nyq.keypress.move_up) then
+ if (ui.vars.clonemon_switch - 2 > 0) then
+ ui.vars.clonemon_switch = ui.vars.clonemon_switch - 2
+ end
+ end
+
+ end
+
+)
--- /dev/null
+return {
+ main = require("states.partybox.main");
+}
--- /dev/null
+return State:new(
+ function()
+ nyq.keypress.trigger = true;
+ if nyq.keypress.back then
+ Pop_state()
+ elseif nyq.keypress.move_right and ui.vars.selected + 1 <= 25 then
+ ui.vars.selected = ui.vars.selected + 1
+ elseif nyq.keypress.move_left and ui.vars.selected - 1 > 0 then
+ ui.vars.selected = ui.vars.selected - 1
+ elseif nyq.keypress.move_down and ui.vars.selected + 5 < 25 then
+ ui.vars.selected = ui.vars.selected + 5
+ elseif nyq.keypress.move_up and ui.vars.selected - 5 >= 0 then
+ ui.vars.selected = ui.vars.selected - 5
+ elseif nyq.keypress.move_east then
+ ui.vars.box_number = (ui.vars.box_number % 4) + 1
+ elseif nyq.keypress.move_west then
+ ui.vars.box_number = ui.vars.box_number - 1
+ if ui.vars.box_number < 1 then ui.vars.box_number = 4 end
+ end
+ end
+)
--- /dev/null
+return {
+ main = require("states.settings.main");
+}
--- /dev/null
+return State:new(
+ function ()
+
+ nyq.keypress.trigger = true;
+ local option = ui.vars.select_options[ui.vars.selected]
+ -- if nyq.keypress.back then
+ if not ui.vars.selected_submenu then
+ if nyq.keypress.back then
+ Pop_state()
+ elseif nyq.keypress.select then
+ if option.name == "go back" then
+ Pop_state()
+ end
+ if option.name == "apply" then
+
+ local speed = nil
+
+ for k, v in pairs(Speed_options) do
+ if v == ui.vars.temp_settings.speed then
+ speed = k
+ print(type(speed))
+ print(speed)
+ end
+ end
+ local t = {
+ controller = ui.vars.temp_settings.controller,
+ fullscreen = ui.vars.temp_settings.fullscreen and 1 or 0,
+ resolution_scale = ui.vars.temp_settings.resolution_scale,
+ speed = speed
+ }
+ Ex.Database.update("config", 1, t)
+
+ Ex.Config.db.controller = t.controller
+
+ ui:notifySet("change", "settings have been updated")
+ elseif option.name == "reset" then
+ ui.vars.temp_settings = copy.shallow_copy({
+ controller = Ex.Config.db.controller,
+ fullscreen = Ex.Config.db.fullscreen,
+ resolution_scale = Ex.Config.db.resolution_scale,
+ speed = Speed_options[Ex.Config.db.speed],
+ })
+ ui:setOptions()
+ elseif option.name == "map controller" then
+ params = {type = "gamepad"}
+ Push_state()
+ state = states.mapping.main
+ temps.ui = uis.mapping
+ elseif option.name == "map keyboard" then
+ params = {type = "keyboard"}
+ Push_state()
+ state = states.mapping.main
+ temps.ui = uis.mapping
+ end
+ ui.vars.selected_submenu = option.options ~= nil
+ elseif nyq.keypress.move_down and (ui.vars.selected + 1 <= ui.vars.selection_max) then
+ ui.vars.selected = ui.vars.selected + 1
+ elseif nyq.keypress.move_up and (ui.vars.selected - 1 > 0) then
+ ui.vars.selected = ui.vars.selected - 1
+ end
+ else
+
+ if nyq.keypress.back then
+ ui.vars.selected_submenu = false
+ elseif nyq.keypress.select then
+ local val = option.options[ui.vars.subselected]
+ local bg_color = {r = 0, g = 0, b = 0, a = 0}
+ local fg_color = {r = 128, g = 128, b = 128, a = 0}
+ local fg_color_selected = {r = 255, g = 255, b = 255, a = 0}
+
+ if ui.vars.temp_settings[option.name] ~= val then
+ v = tostring(val)
+ if option.name == "speed" then
+ v = "x" .. v
+ end
+
+ ui:textChange("menu", option.name, option.name .. ": " .. v, fg_color, bg_color)
+ ui:textChange("menu", option.name .. " selected", option.name .. ": " .. v, fg_color_selected, bg_color)
+ ui.vars.temp_settings[option.name] = val
+
+ ui.vars.restart_required = false
+
+ for k, v in pairs(ui.vars.temp_settings) do
+ if (v ~= Ex.Config.db[k]) and (k ~= "controller") then
+ ui.vars.restart_required = true
+ break
+ end
+ end
+
+ end
+ ui.vars.subselected = 1
+ ui.vars.selected_submenu = false
+ elseif nyq.keypress.move_down and (ui.vars.subselected + 1 <= ui.vars.subselection_max) then
+ ui.vars.subselected = ui.vars.subselected + 1
+ elseif nyq.keypress.move_up and (ui.vars.subselected - 1 > 0) then
+ ui.vars.subselected = ui.vars.subselected - 1
+ end
+ end
+
+ end
+)
--- /dev/null
+return {
+ main = require("states.start.main");
+}
--- /dev/null
+return State:new(
+ function ()
+ nyq.keypress.trigger = true;
+ if nyq.keypress.select then
+ -- terminal.commands.world()
+ players = Ex.Database.getAll("players") or {nil}
+ -- print("loading all players: \n")
+ -- for k, v in pairs(players) do
+ -- for k2, v2 in pairs(v) do
+ -- print(k2, v2)
+ -- end
+ -- print()
+ -- end
+ -- temps.ui = uis.loadsave
+ -- state = states.loadsave.main
+ state = states.start_menu.main
+ temps.ui = uis.start_menu
+ elseif nyq.keypress.change_moves1 then
+ -- pretend like this is a new file
+ -- Ex.Database.insert("moves", {
+ -- name = "NONE",
+ -- pp = 0,
+ -- power = 0
+ -- })
+ -- Ex.Database.insert("moves", {
+ -- name = "kick",
+ -- pp = 200,
+ -- power = 20
+ -- })
+ -- Ex.Database.insert("pokemon", {
+ -- name = "charzard",
+ -- type = 1,
+ -- gender = 0,
+ -- move_one_id = 1,
+ -- move_two_id = 1,
+
+ -- })
+ -- Ex.Database.insert("players", {
+ -- name = "ash",
+ -- uuid = Ex.Database.uuid(),
+ -- age = 33,
+ -- pokemon_id = 1
+ -- })
+ -- Ex.Database.insert("people", {
+ -- name = "blue",
+ -- age = 500,
+ -- level = 10,
+ -- spritesheet = "sup.png"
+ -- })
+ -- Ex.Database.insert("players", {
+ -- uuid Ex.Database.uuid(),
+ -- person_id = 2
+ -- })
+ end
+ end
+)
--- /dev/null
+return {
+ main = require("states.start_menu.main")
+}
--- /dev/null
+return State:new(
+ function ()
+ nyq.keypress.trigger = true;
+ if nyq.keypress.select then
+ if ui.vars.selected == ui.vars.select_options["play"] then
+ state = states.loadsave.main
+ temps.ui = uis.loadsave
+ elseif ui.vars.selected == ui.vars.select_options["settings"] then
+ Push_state()
+ state = states.settings.main
+ temps.ui = uis.settings
+ end
+ elseif nyq.keypress.move_down and (ui.vars.selected + 1 <= ui.vars.selection_max) then
+ ui.vars.selected = ui.vars.selected + 1
+ elseif nyq.keypress.move_up and (ui.vars.selected - 1 > 0) then
+ ui.vars.selected = ui.vars.selected - 1
+ end
+ end
+)
--- /dev/null
+return {
+ main = require("states.world.main");
+ pause = require("states.world.pause");
+ text = require("states.world.text");
+ option = require("states.world.option");
+}
--- /dev/null
+return State:new(
+ function()
+ nyq.keypress.trigger = false;
+ if (nyq.keypress.pause) then
+ state = states.world.pause
+ end
+
+ ui.ai:collisionUpdate()
+
+ if nyq.keypress.move_north then
+ ui.ai:travel("north")
+ elseif nyq.keypress.move_east then
+ ui.ai:travel("east")
+ elseif nyq.keypress.move_south then
+ ui.ai:travel("south")
+ elseif nyq.keypress.move_west then
+ ui.ai:travel("west")
+ end
+ end
+)
--- /dev/null
+return State:new(
+ function()
+ nyq.keypress.trigger = true;
+ if (nyq.keypress.select) then
+ state = states.world.text
+ ui.vars.text_pos = ui.vars.text_pos + 1
+ elseif (nyq.keypress.move_down) and ui.vars.selected < ui.vars.selection_max then
+ ui.vars.selected = ui.vars.selected + 1
+ elseif (nyq.keypress.move_up) and ui.vars.selected > 1 then
+ ui.vars.selected = ui.vars.selected - 1
+ end
+end)
--- /dev/null
+return State:new(
+ function()
+ nyq.keypress.trigger = true;
+ if (nyq.keypress.select) then
+ if ui.vars.selected == 6 then
+ Push_state()
+ states.settings.main:reset()
+ state = states.settings.main
+ temps.ui = uis.settings
+ end
+ if ui.vars.selected == 7 then
+ nyq.exit()
+ end
+ if ui.vars.selected == 3 then
+ Push_state()
+ states.bag.main:reset()
+ state = states.bag.main
+ temps.ui = uis.bag
+ params = {
+ items = {
+ [1] = {
+ name = "book",
+ description = "can read it",
+ image = "",
+ quantity = 1
+ },
+ [2] = {
+ name = "cup",
+ description = "drink things",
+ image = "",
+ quantity = 2
+ },
+ [3] = {
+ name = "pencil",
+ description = "write things",
+ image = "",
+ quantity = 3
+ }
+ },
+ berries = {
+ [1] = {
+ name = "blueberry",
+ description = "improves stats",
+ image = "",
+ quantity = 1
+ },
+ [2] = {
+ name = "raseberry",
+ description = "raises defense stat",
+ image = "",
+ quantity = 2
+ },
+ [3] = {
+ name = "blackberry",
+ description = "clears status effects",
+ image = "",
+ quantity = 3
+ }
+ },
+ cloneballs = {
+ [1] = {
+ name = "ULTRA BALL",
+ description = "A better Ball with a higher catch rate than a Great Ball",
+ image = "",
+ quantity = 1
+ },
+ [2] = {
+ name = "NET BALL",
+ description = "A BALL that works on WATER- and BUG- type Clonemon",
+ image = "",
+ quantity = 2
+ },
+ }
+ }
+ end
+ if ui.vars.selected == 2 then
+ Push_state()
+ states.party.main:reset()
+ params = {
+ my_clonemon = my_clonemon
+ }
+ state = states.party.main
+ temps.ui = uis.party
+
+ end
+ if ui.vars.selected == 4 then
+ Push_state()
+ params = {
+ -- entry = "test",
+ -- moves = moves.charzard,
+ rivals_pokemon = {
+ [1] = {
+ name = "meowth",
+ },
+ },
+ my_pokemon = {
+ name = "charzard",
+ moves = moves.charzard,
+ level = 100,
+ },
+ player = {
+ name = "nyquist"
+ }
+ }
+ uis.world.paused = false
+ state = states.battle.enterBattle
+ temps.ui = uis.battle
+ end
+ end
+ if (nyq.keypress.pause) or (nyq.keypress.back) then
+ -- temps.state = states.world.main
+ state = states.world.main
+ end
+ if (nyq.keypress.move_down) then
+ if (ui.vars.selected + 1 <= ui.vars.menu_size) then
+ ui.vars.selected = ui.vars.selected + 1
+ end
+ elseif (nyq.keypress.move_up) then
+ if (ui.vars.selected - 1 > 0) then
+ ui.vars.selected = ui.vars.selected - 1
+ end
+ end
+ end
+)
--- /dev/null
+return State:new(
+ function()
+ nyq.keypress.trigger = true;
+ if (nyq.keypress.select) then
+ if ui.vars.text_done then
+ -- temps.state = states.world.main
+ state = states.world.main
+ ui.vars.text_pos = 0
+ ui.vars.text_done = false
+ ui.vars.text_end = true
+ elseif (ui.vars.text_pos < ui.vars.text_max) then
+ ui.vars.text_pos = ui.vars.text_pos + 1
+ end
+
+ end
+end)
--- /dev/null
+#!/usr/bin/env bash
+
+STEAMROOT="$(cd "${0%/*}" && echo $PWD)"
+STEAMEXE=`basename "$0" .sh`
+
+UNAME=`uname`
+if [ "$UNAME" == "Linux" ]; then
+ PLATFORM=linux32
+ export LD_LIBRARY_PATH="$STEAMROOT/$PLATFORM:$LD_LIBRARY_PATH"
+else # if [ "$UNAME" == "Darwin" ]; then
+ PLATFORM=osx32
+ export DYLD_LIBRARY_PATH="$STEAMROOT/$PLATFORM:$DYLD_LIBRARY_PATH"
+fi
+
+ulimit -n 2048
+
+MAGIC_RESTART_EXITCODE=42
+
+if [ "$DEBUGGER" == "gdb" ] || [ "$DEBUGGER" == "cgdb" ]; then
+ ARGSFILE=$(mktemp $USER.steam.gdb.XXXX)
+
+ # Set the LD_PRELOAD varname in the debugger, and unset the global version.
+ if [ "$LD_PRELOAD" ]; then
+ echo set env LD_PRELOAD=$LD_PRELOAD >> "$ARGSFILE"
+ echo show env LD_PRELOAD >> "$ARGSFILE"
+ unset LD_PRELOAD
+ fi
+
+ $DEBUGGER -x "$ARGSFILE" "$STEAMROOT/$PLATFORM/$STEAMEXE" "$@"
+ rm "$ARGSFILE"
+else
+ $DEBUGGER "$STEAMROOT/$PLATFORM/$STEAMEXE" "$@"
+fi
+
+STATUS=$?
+
+if [ $STATUS -eq $MAGIC_RESTART_EXITCODE ]; then
+ exec "$0" "$@"
+fi
+exit $STATUS
--- /dev/null
+#!/usr/bin/env bash
+
+STEAMROOT="$(cd "${0%/*}" && echo $PWD)"
+STEAMCMD=`basename "$0" .sh`
+
+UNAME=`uname`
+if [ "$UNAME" == "Linux" ]; then
+ STEAMEXE="${STEAMROOT}/linux32/${STEAMCMD}"
+ PLATFORM="linux32"
+ export LD_LIBRARY_PATH="$STEAMROOT/$PLATFORM:$LD_LIBRARY_PATH"
+else # if [ "$UNAME" == "Darwin" ]; then
+ STEAMEXE="${STEAMROOT}/${STEAMCMD}"
+ if [ ! -x ${STEAMEXE} ]; then
+ STEAMEXE="${STEAMROOT}/Steam.AppBundle/Steam/Contents/MacOS/${STEAMCMD}"
+ fi
+ export DYLD_LIBRARY_PATH="$STEAMROOT:$DYLD_LIBRARY_PATH"
+ export DYLD_FRAMEWORK_PATH="$STEAMROOT:$DYLD_FRAMEWORK_PATH"
+fi
+
+ulimit -n 2048
+
+MAGIC_RESTART_EXITCODE=42
+
+if [ "$DEBUGGER" == "gdb" ] || [ "$DEBUGGER" == "cgdb" ]; then
+ ARGSFILE=$(mktemp $USER.steam.gdb.XXXX)
+
+ # Set the LD_PRELOAD varname in the debugger, and unset the global version.
+ if [ "$LD_PRELOAD" ]; then
+ echo set env LD_PRELOAD=$LD_PRELOAD >> "$ARGSFILE"
+ echo show env LD_PRELOAD >> "$ARGSFILE"
+ unset LD_PRELOAD
+ fi
+
+ $DEBUGGER -x "$ARGSFILE" "$STEAMEXE" "$@"
+ rm "$ARGSFILE"
+else
+ $DEBUGGER "$STEAMEXE" "$@"
+fi
+
+STATUS=$?
+
+if [ $STATUS -eq $MAGIC_RESTART_EXITCODE ]; then
+ exec "$0" "$@"
+fi
+exit $STATUS
--- /dev/null
+Content Manifest for Depot 2762581
+
+Manifest ID / date : 0 / Wed Dec 31 19:00:00 1969
+Total number of files : 169
+Total number of chunks : 0
+Total bytes on disk : 0
+Total bytes compressed : 0
+CRC raw / encrypted : 0x0 / 0x0
+
+ Size Chunks File SHA Flags Name
+ 0 0 0000000000000000000000000000000000000000 40 .cache
+ 0 0 0000000000000000000000000000000000000000 40 .cache\formats
+ 2 1 1489f923c4dca729178b3e3233458550d8dddf29 0 .cache\formats\0
+ 2 1 1489f923c4dca729178b3e3233458550d8dddf29 0 .cache\formats\1
+ 111 1 bec6820df48d54720627d0868d564ad27bb58973 0 .cache\formats\2
+ 2 1 1489f923c4dca729178b3e3233458550d8dddf29 0 .cache\formats\3
+ 2 1 1489f923c4dca729178b3e3233458550d8dddf29 0 .cache\formats\4
+ 2 1 1489f923c4dca729178b3e3233458550d8dddf29 0 .cache\formats\5
+ 2 1 1489f923c4dca729178b3e3233458550d8dddf29 0 .cache\formats\6
+ 2 1 1489f923c4dca729178b3e3233458550d8dddf29 0 .cache\formats\7
+ 2 1 1489f923c4dca729178b3e3233458550d8dddf29 0 .cache\formats\8
+ 2 1 1489f923c4dca729178b3e3233458550d8dddf29 0 .cache\formats\9
+ 0 0 0000000000000000000000000000000000000000 40 database
+ 2,028 1 4605fd37e95398e34017f5bda75df73bd78510bc 0 database\init.lua
+ 9,290 1 f50b42d051690447584033c17b5b0c63b274c24d 0 init.lua
+ 265,216 1 94d39c6fc6540dc077b3c7bed4ce3cfac1acd171 0 libmodplug-1.dll
+ 25,600 1 1d0919202c0705439f2f0b395e80fdff12974afa 0 libogg-0.dll
+ 368,128 1 9e92bcd41d9f137530e6a8681e1cfe6c8e21d224 0 libopus-0.dll
+ 46,592 1 53840bd4b39fc1c51d0f4566441c5e3cb4f0393f 0 libopusfile-0.dll
+ 210,944 1 e3d1403be06beb32fc8dc7e8a58c31e18b586a70 0 libpng16-16.dll
+ 285,184 1 f7c6a50a32e37775e40cc83f960553ec75217951 0 lua53.dll
+ 259,072 1 55bff0e9ed6b35b2a8fd56aa495da3c56239c7af 0 mapeditor.exe
+ 0 0 0000000000000000000000000000000000000000 40 map_configs
+ 4,534 1 e775926638259944cf570fda1a31dba74b99ea75 0 map_configs\mapeditor_config.lua
+ 638,658 1 9d2d0ec283cf223b8a345a82bdf9f32c637c023b 0 n2de.exe
+ 0 0 0000000000000000000000000000000000000000 40 resources
+ 0 0 0000000000000000000000000000000000000000 40 resources\data
+ 0 0 0000000000000000000000000000000000000000 40 resources\data\test
+ 519 1 f572c121744fa33ae8bbfda7f661393b5328ee70 0 resources\data\test\map2.dat
+ 889 1 73ceac29c4eece82049306d3c38ad89f3ad0e769 0 resources\data\test\objects2.dat
+ 0 0 0000000000000000000000000000000000000000 40 resources\fonts
+ 510,612 1 1e3ada8fee1f9631cc8e85c1720b5cfe02f8f59c 0 resources\fonts\NotoSansMono-Regular.ttf
+ 0 0 0000000000000000000000000000000000000000 40 resources\images
+ 2,308 1 a899f8d629784e5b747196580f2b56d8fa3070c3 0 resources\images\axolotl.png
+ 1,085 1 97d0784672ff08951d856aea07da284044efe3a3 0 resources\images\bag.png
+ 16,259 1 00558a37edd2ac4852b38dccef6d9baeccddcb94 0 resources\images\battle_ui.png
+ 32,658 1 33e7b533bb1ac12f11643835cb7186ee1d91d28b 0 resources\images\berry_one.png
+ 435 1 dbe69edeb2c9e1c067f98265a54601a89ac33a91 0 resources\images\border1.png
+ 324 1 cf0842593e692b196cd142408e38cd7a1d823c51 0 resources\images\border1_unselected.png
+ 213 1 56feef6c5d8f6c4a3129feb01ec46ffb1e944aed 0 resources\images\border2..png
+ 301 1 532f2ac06759e2143a73d113ae5e5de1a3196c18 0 resources\images\border2.png
+ 187 1 a8dad63e630aa14ffadf2e8d38400a277bae614f 0 resources\images\border2_unselected.png
+ 37,137 1 0d59b9d04f38191f7cf42189f7e9a429aa926994 0 resources\images\character_spritesheet_1.png
+ 4,044 1 e9cd7f0d6aa75340206dceff1d102dbd5c13d7e5 0 resources\images\choice_select_test_one.png
+ 5,342 1 4d363e8cc021ba6b0377e8da8273ab769b941fe1 0 resources\images\choice_select_test_two.png
+ 141,573 1 6a06e91c091d713e2fad9df25e0e0a3c9b35fbd3 0 resources\images\clonemon.png
+ 135,878 1 99d0cf95fea23e012bba16e06a5e271d0cbfd9f0 0 resources\images\clonemon_battle_grass.png
+ 7,735 1 4e5c57f756003815cb6e3f79628dd7032f8b8bd2 0 resources\images\clonemon_battle_ui.png
+ 1,391 1 cdc6b037763732ef67af8af6452579dccd934a22 0 resources\images\clonemon_battle_ui_grass.png
+ 14,530 1 79e13032d63472706dc99eeb850232449d1c50ab 0 resources\images\clonemon_party.png
+ 55,427 1 1cdbc2c4fd38c881f970eb87491f722b27595a80 0 resources\images\generic_house_one.png
+ 21,647 1 28ca85cd00439b5acf687f3569233cc3544abefe 0 resources\images\gradient.png
+ 50,793 1 03e8ab59576236e01313c53e84526db7e79b561c 0 resources\images\house_two.png
+ 20,953 1 e5f6e17b7ce334ecb6c96fe714683b31558392d1 0 resources\images\keyboard_lower.png
+ 23,212 1 3d377ba00bb4998d62a8eb889fdbe9c1e2a7a96f 0 resources\images\keyboard_upper.png
+ 7,430 1 8f8ba42e54bc992a16cc77ce9138e94cb5ab5d0b 0 resources\images\loadsave.png
+ 4,560 1 97f87a383cd02831f3f2a78e299b5cccd72061b4 0 resources\images\logo.png
+ 807 1 3600eb2b9b85f738f73e93d2815f9bce6e910576 0 resources\images\menu_items.png
+ 11,743 1 81e7b91c29d10f4124ccb8aaeb768e6bd7c1f8e2 0 resources\images\nyquist.png
+ 150,349 1 404910c2429dd55fa13beab1281a25b4d905daf4 0 resources\images\nyquist.xcf
+ 10,059 1 c11893a53e805c34348fd45ad19d1f1d52962178 0 resources\images\nyquist2.png
+ 39,812 1 8dd757f3814d85ca1cede6f1c95ac392f4143b5a 0 resources\images\nyquist_spritesheet.png
+ 11,059 1 27c24c310d40937d5f318cdf0264a9d387431d00 0 resources\images\nyquist_spritesheet3.png
+ 55,934 1 9425882cf965ad83f92c571e60d9736e9df4c574 0 resources\images\outdoors_backgorund_one.png
+ 5,896 1 3e32e1e011535228dd783e5abd9b4e2e73bce89c 0 resources\images\pause.png
+ 19,880 1 4b583b722341d067354541cc5a49ccc07f75540b 0 resources\images\potion_one.png
+ 15,876 1 89ed067d607ca73595e6cddc6702f6831b393881 0 resources\images\potion_two.png
+ 29,620 1 300898079938011f2018985fa3e3192522db0291 0 resources\images\Route_111.png
+ 18,820 1 cde85671294535a7b6929f251de23ec4617ff824 0 resources\images\tileset_indoors_1.png
+ 40,478 1 a2dc8443922c13d616cbac87332c937b3f46b750 0 resources\images\tileset_outside_1.png
+ 163,112 1 bad98f6103e0f628e5c441886aa962a93288bc21 0 resources\images\town4.png
+ 16,266 1 443dea0d5ea56b5c98fa35d45922d0b21592d677 0 resources\images\tree_one.png
+ 17,176 1 25294231343dddf7a336b85c2980c4a44ca0441d 0 resources\images\tree_two.png
+ 197,816 1 6bb6fc848997b1c773e4937b51d598e56357e424 0 resources\images\vs.png
+ 104,796 1 af7955f837d3c8e2860d7e3b81318c743fc8e2bb 0 resources\images\vs2.png
+ 99,385 1 b6656b952f835d46633e14c74b83ec0fd2447899 0 resources\images\vs3.png
+ 10,409 1 05742d69b3673b2bcfa9d4c2e3c9d0fbcc517291 0 resources\images\well.png
+ 118,784 1 aa7bbb2e79372465a69bdcf23c6883595a0f3ddc 0 resources\test.db
+ 0 0 0000000000000000000000000000000000000000 40 resources\wavs
+ 8,532,208 9 b33571119a1ca99d86741946e686e654c4976194 0 resources\wavs\battle1.wav
+ 150,003 1 4390c0dbde32bbb68d980b50c042e7d7a2a935ba 0 resources\wavs\battle1.wav.asd
+ 2,730,712 3 2c694dde8a2fc9cc7c535502613272334ce34c9e 0 resources\wavs\breakdown1.wav
+ 50,516 1 a519b95d132027ab4a896500ee500b3c1efe8482 0 resources\wavs\breakdown1.wav.asd
+ 14,946,216 15 3b2934f77513d1cc8280caf6d9e2196c26e6379a 0 resources\wavs\chipped.wav
+ 259,795 1 c05760a58fa845bd3d1bc61d993884895e6d08de 0 resources\wavs\chipped.wav.asd
+ 18,812,964 18 16b060274000913162de4d6fd63ad7515c3ce835 0 resources\wavs\chipped_dip.wav
+ 317,091 1 bb22cad0a718421c34a11898f4ad5824961b5b98 0 resources\wavs\chipped_dip.wav.asd
+ 903,496 1 45bdce858a5fca6bf2729a05b75ade82c0c6e66e 0 resources\wavs\clonks.wav
+ 12,125,410 12 3ab27b042a71671b4371192e52b8d3d0bb6ce9e3 0 resources\wavs\destructo.wav
+ 17,280,044 17 3d968fab67de0c13477cd52bb1111c18758fecfe 0 resources\wavs\good.wav
+ 302,049 1 97c9a19afa5c46c67b049d56f097703a0310e433 0 resources\wavs\good.wav.asd
+ 7,986 1 126a3fa63da6630657c895ecc050a7822c3faa46 0 resources\wavs\hihat.wav
+ 10,237,016 10 1acd1ca494596b9dc15d2d55b00cf663c012cd60 0 resources\wavs\intro.wav
+ 25,530 1 111f70d2c36c78b9682e21de0355f8e80ed3409e 0 resources\wavs\kick.wav
+ 1,893,948 2 3e75d65b7d4a03609a0402246c5281573997abaa 0 resources\wavs\melody.mp3
+ 17,953,648 18 955fe087f220dd49c8697bd6824f6dcbd9bfa3db 0 resources\wavs\meta19.wav
+ 313,605 1 249d44320035b9d18c2717e42be4858142c3b620 0 resources\wavs\meta19.wav.asd
+ 2,393,812 3 daa7e5f7eace4539d93908dd89303385e3e702db 0 resources\wavs\mutate.wav
+ 45,252 1 41a2f55a03b6639aded29bcd0acb61411c0791ab 0 resources\wavs\mutate.wav.asd
+ 13,100,060 13 c7a9065d0481efaf6585c6b99032f2437ca5c593 0 resources\wavs\pianer1.wav
+ 227,727 1 798190b55189c0b9cc9237b0f5c20867ee810d22 0 resources\wavs\pianer1.wav.asd
+ 512,044 1 c6612c8cc25a2cd1a531e8d95d368cab53376af7 0 resources\wavs\rise.wav
+ 12,708 1 e1b7938ee70f0ebece0c4220189efd8f45a2d485 0 resources\wavs\rise.wav.asd
+ 2,730,712 3 9a29fe4a1d8123d8887178288512f68c662dab20 0 resources\wavs\rise2.wav
+ 845,644 1 c9e3a849ccafa77154c31a041f2b656ffb8a77eb 0 resources\wavs\rise3.wav
+ 8,666 1 26618105e72d2cb25338b2111b4c6e3635450bb8 0 resources\wavs\snare.wav
+ 2,233,552 3 23a8c4aed780bb334119606566a60b44fd027861 0 resources\wavs\TOD.mp3
+ 1,623,592 2 9a5b0152d171fc5788aef24e03e54ced9dd2cfa2 0 resources\wavs\um_intro.wav
+ 1,725,064 2 2500e40ce8bb1d5653d61a15b24a8873d2dd1a49 0 resources\wavs\um_main.wav
+ 455,707 1 b4c4a0ad7e377fb0df73967d2d0dbc0b9fd0929a 0 resources\wavs\you_are_gay.mp3
+ 2,255,872 3 3b80b1228631abbb7f2745828a25cbce0d9dce09 0 SDL2.dll
+ 125,440 1 b03bb9d09447114a018110bfb91d56ef8d5ec3bb 0 SDL2_image.dll
+ 285,184 1 b58b433009fe14286748a1fa11cd2faa7585acfd 0 SDL2_mixer.dll
+ 1,561,088 2 808ff63ce1ebfcd734a0bb797fc01c9ef5615563 0 SDL2_ttf.dll
+ 2,159,616 3 113a7cc6a35483ee09fc0d9c40a4fd2a763f24de 0 sqlite3.dll
+ 0 0 0000000000000000000000000000000000000000 40 states
+ 0 0 0000000000000000000000000000000000000000 40 states\bag
+ 52 1 299499edd8d60b7799d7de8b5e42a2249febcf42 0 states\bag\init.lua
+ 754 1 6fb8f72dd2b86b5b8a567e2380f2e5a335e9ec64 0 states\bag\main.lua
+ 0 0 0000000000000000000000000000000000000000 40 states\battle
+ 1,213 1 4fbeee17bf20a3706e042415135d44cafed564c0 0 states\battle\doSelect.lua
+ 380 1 1eb978284f6963f324a7e8116e45d2aa92a51add 0 states\battle\enterBattle.lua
+ 176 1 a8bc483ffcbf90bb7130003b20b0d698048a0abf 0 states\battle\init.lua
+ 922 1 6f5a706f9ca273cb59f4b3afea0c83682509b01e 0 states\battle\moveSelect.lua
+ 0 0 0000000000000000000000000000000000000000 40 states\choice_select
+ 61 1 731ed20200b80f0d59dbd0d29561cd1939b6a6c9 0 states\choice_select\init.lua
+ 338 1 61bd159678eddbbcef58126a5a53a17ca0e21b0c 0 states\choice_select\main.lua
+ 0 0 0000000000000000000000000000000000000000 40 states\enter_text
+ 58 1 44d1db296666c3fd30221fa7ad6e68a5870895ba 0 states\enter_text\init.lua
+ 2,668 1 ac22f64cba766a319d24fd3906f52a56534d16e6 0 states\enter_text\main.lua
+ 526 1 6d4e897c7af5f20d76a1cc0324795bc91544cf97 0 states\init.lua
+ 0 0 0000000000000000000000000000000000000000 40 states\loadsave
+ 56 1 19a6bac92a99da327ee9dc7ed5e6f01e071844dc 0 states\loadsave\init.lua
+ 1,808 1 d70d295159d96b6750b4436d83dbef61af99936d 0 states\loadsave\main.lua
+ 0 0 0000000000000000000000000000000000000000 40 states\party
+ 686 1 0d440eb6b9ddf59004d3d9a58ad111e5f372c1af 0 states\party\doWhat.lua
+ 148 1 7881f6dd0ca105b46f931480cff4a9c18704a557 0 states\party\init.lua
+ 1,284 1 32d94a8642ff57d9b6e952d07db55a8fdd0e9168 0 states\party\main.lua
+ 1,429 1 7cb8bf6dd706a5c74501d8639042c9c461a49f5b 0 states\party\switch.lua
+ 0 0 0000000000000000000000000000000000000000 40 states\settings
+ 57 1 56bb8b5fd239ef34cb48b82f1c8df1aecd289602 0 states\settings\init.lua
+ 44 1 35269f8e7a1d0d8420c6054a356a30ec6b025219 0 states\settings\main.lua
+ 0 0 0000000000000000000000000000000000000000 40 states\start
+ 53 1 5fad90cca7e88040a4e9770de16e5f07ccde265c 0 states\start\init.lua
+ 1,780 1 f18a204fa95e30b1db118a7b9e031e7036b311e4 0 states\start\main.lua
+ 0 0 0000000000000000000000000000000000000000 40 states\start_menu
+ 58 1 150a71bc5e5e4c9d787440ffb82061a99f4ce17c 0 states\start_menu\init.lua
+ 683 1 c7a0257b1df676bd396027a4a53c3e175d05e842 0 states\start_menu\main.lua
+ 0 0 0000000000000000000000000000000000000000 40 states\world
+ 189 1 f577bfd6c53773633bd0400ce72926aa6afaca41 0 states\world\init.lua
+ 636 1 d6a5c62bb4fc56e3478140550f38f9903b55d2bb 0 states\world\main.lua
+ 482 1 fb2fb310725db843473b70a1148eadc7690047b1 0 states\world\option.lua
+ 1,036 1 4bedec3948df0fa390d3fdedf6045dbd2dd29522 0 states\world\pause.lua
+ 470 1 6af2c446ddf25dbc2c9849f6d680b4e5f17cf2a5 0 states\world\text.lua
+ 5,700 1 f5f4016b45adf9ae3a0e12a02f5f0b45bc90c205 0 terminal.lua
+ 0 0 0000000000000000000000000000000000000000 40 uis
+ 4,035 1 85b6e15b628f6451291f053888c2533217a1d3a2 0 uis\bag.lua
+ 7,320 1 0c26d92a11f8cbf74676f7c11ba9a15de8d4043f 0 uis\battle.lua
+ 1,354 1 27fb59758a46dc418df0a3ac587d8389e14a8529 0 uis\choice_select.lua
+ 5,537 1 91954f51f6e8e4379f7ca9043db753427c7f8e5d 0 uis\enter_text.lua
+ 462 1 ac848ad940595378854ecfc6afa9a8683c6b02d5 0 uis\init.lua
+ 3,379 1 49c7a7de483945ef2b443ae129a9b62bdb96e03a 0 uis\loadsave.lua
+ 6,358 1 8ed12f6c2eccd66b6fbee747e605d45b574b7717 0 uis\party.lua
+ 341 1 8a5c0858f53d6a8bdc695ae1a2798f977a744721 0 uis\pause.lua
+ 1,017 1 d84c80ec4f12754ea9674ab3701e74061c24a750 0 uis\settings.lua
+ 3,016 1 cdac401c82dfc97a1e16af7c830b8dd7dc62332c 0 uis\start.lua
+ 1,251 1 a323e64c317d2a3e7f5cf6c8c07dfc2708145eb5 0 uis\start_menu.lua
+ 11,964 1 f0cf8e949f1dc0dcc0a36617d48128746d2b504a 0 uis\world.lua
+ 108,544 1 ec3f6cf88711ef8cfb3cc439cb75471a2bb9e1b5 0 zlib1.dll
--- /dev/null
+[2024-01-18 03:58:54]: Starting AppID 2762580 build (flags 0x0).
+[2024-01-18 03:58:54]: Building depot 2762581...
+
+[2024-01-18 03:59:01]: Successfully finished AppID 2762580 build (BuildID 13203732).
--- /dev/null
+[2024-01-18 03:58:54]: Starting build for depot 2762581, content path is "/mnt/c/Users/sahww/Development/github/clonemon/steam/ContentBuilder/content/", build flags 0x0
+[2024-01-18 03:58:54]: Building file listing for depot 2762581 ...
+[2024-01-18 03:58:56]: Found 260 files for mapping: /mnt/c/Users/sahww/Development/github/clonemon/steam/ContentBuilder/content/windows * -> .
+[2024-01-18 03:58:56]: Found 260 files (138 MB) for depot 2762581
+[2024-01-18 03:58:56]: Building depot 2762581, baseline manifest 4792084950510594223 (217 files)
+[2024-01-18 03:58:57]: Found 330 chunks ( 286 used previously ) for depot 2762581, took 0 minutes, 0 seconds
+[2024-01-18 03:58:57]: Changes to baseline manifest 4792084950510594223 :
+[2024-01-18 03:58:57]: Added : ".init.lua.swp" 20 kB
+[2024-01-18 03:58:57]: Changed: "extensions\audio\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Added : "extensions\config" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "extensions\config\init.lua" 3 kB
+[2024-01-18 03:58:57]: Added : "extensions\config\mappings" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "extensions\config\mappings\default_gamepad.lua" 1 kB
+[2024-01-18 03:58:57]: Added : "extensions\config\mappings\default_keyboard.lua" 1 kB
+[2024-01-18 03:58:57]: Added : "extensions\config\mappings\init.lua" 1 kB
+[2024-01-18 03:58:57]: Changed: "extensions\database\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "extensions\database\schema.lua" 2 kB size, 2 kB changed
+[2024-01-18 03:58:57]: Added : "extensions\images" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "extensions\images\init.lua" 1 kB
+[2024-01-18 03:58:57]: Added : "extensions\init.lua" 1 kB
+[2024-01-18 03:58:57]: Changed: "extensions\libaudio.dll" 156 kB size, 156 kB changed
+[2024-01-18 03:58:57]: Changed: "extensions\libdatabase.dll" 163 kB size, 163 kB changed
+[2024-01-18 03:58:57]: Added : "extensions\libimages.dll" 161 kB
+[2024-01-18 03:58:57]: Added : "extensions\libloops.dll" 159 kB
+[2024-01-18 03:58:57]: Added : "extensions\libsprites.dll" 163 kB
+[2024-01-18 03:58:57]: Changed: "extensions\libterminal.dll" 155 kB size, 155 kB changed
+[2024-01-18 03:58:57]: Added : "extensions\libtext.dll" 161 kB
+[2024-01-18 03:58:57]: Added : "extensions\loops" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "extensions\loops\init.lua" 1 kB
+[2024-01-18 03:58:57]: Added : "extensions\metatables" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "extensions\metatables\ui.lua" 16 kB
+[2024-01-18 03:58:57]: Added : "extensions\sprites" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "extensions\sprites\init.lua" 1 kB
+[2024-01-18 03:58:57]: Changed: "extensions\terminal\commands.lua" 4 kB size, 4 kB changed
+[2024-01-18 03:58:57]: Changed: "extensions\terminal\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Added : "extensions\text" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "extensions\text\init.lua" 1 kB
+[2024-01-18 03:58:57]: Changed: "init.lua" 7 kB size, 7 kB changed
+[2024-01-18 03:58:57]: Added : "lua-5.4.6.tar.gz" 355 kB
+[2024-01-18 03:58:57]: Added : "lua54.dll" 347 kB
+[2024-01-18 03:58:57]: Changed: "mapeditor.exe" 199 kB size, 199 kB changed
+[2024-01-18 03:58:57]: Added : "map_configs\controls" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "map_configs\controls\controls.lua" 1 kB
+[2024-01-18 03:58:57]: Added : "map_configs\crops" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "map_configs\crops\indoor.lua" 3 kB
+[2024-01-18 03:58:57]: Added : "map_configs\crops\outdoor.lua" 2 kB
+[2024-01-18 03:58:57]: Added : "map_configs\indoor1.lua" 1 kB
+[2024-01-18 03:58:57]: Added : "map_configs\outdoor1.lua" 1 kB
+[2024-01-18 03:58:57]: Added : "modules\ai.lua" 4 kB
+[2024-01-18 03:58:57]: Changed: "modules\clock.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "modules\collection.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "modules\copy.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "modules\find.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "modules\hashTable.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Added : "modules\metatables" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "modules\metatables\entity.lua" 3 kB
+[2024-01-18 03:58:57]: Added : "modules\player.lua" 1 kB
+[2024-01-18 03:58:57]: Changed: "modules\state.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "modules\string.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "modules\table.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "modules\uuid.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Added : "modules\world.lua" 10 kB
+[2024-01-18 03:58:57]: Changed: "n2de.exe" 132 kB size, 132 kB changed
+[2024-01-18 03:58:57]: Changed: "README.adoc" 3 kB size, 3 kB changed
+[2024-01-18 03:58:57]: Added : "resources\data\test\map1.dat" 1 kB
+[2024-01-18 03:58:57]: Changed: "resources\data\test\map2.dat" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Added : "resources\data\test\map3.dat" 1 kB
+[2024-01-18 03:58:57]: Added : "resources\data\test\map4.dat" 1 kB
+[2024-01-18 03:58:57]: Added : "resources\data\test\map5.dat" 1 kB
+[2024-01-18 03:58:57]: Added : "resources\data\test\map6.dat" 1 kB
+[2024-01-18 03:58:57]: Added : "resources\data\test\map7.dat" 1 kB
+[2024-01-18 03:58:57]: Added : "resources\data\test\objects1.dat" 1 kB
+[2024-01-18 03:58:57]: Changed: "resources\data\test\objects2.dat" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Added : "resources\data\test\objects3.dat" 1 kB
+[2024-01-18 03:58:57]: Added : "resources\data\test\objects4.dat" 1 kB
+[2024-01-18 03:58:57]: Added : "resources\data\test\objects5.dat" 1 kB
+[2024-01-18 03:58:57]: Added : "resources\data\test\objects6.dat" 3 kB
+[2024-01-18 03:58:57]: Added : "resources\data\test\objects7.dat" 1 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_indoor_1.png" 13 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_indoor_2.png" 10 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_outdoor1.png" 170 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_outdoor_1.png" 6 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_outdoor_10.png" 6 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_outdoor_2.png" 6 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_outdoor_3.png" 6 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_outdoor_4.png" 6 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_outdoor_5.png" 6 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_outdoor_6.png" 6 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_outdoor_7.png" 6 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_outdoor_8.png" 6 kB
+[2024-01-18 03:58:57]: Added : "resources\images\map_outdoor_9.png" 6 kB
+[2024-01-18 03:58:57]: Changed: "resources\images\menu_items.png" 6 kB size, 6 kB changed
+[2024-01-18 03:58:57]: Added : "resources\images\spritesheet_indoors_1.backup.png" 24 kB
+[2024-01-18 03:58:57]: Changed: "resources\images\spritesheet_indoors_1.png" 21 kB size, 21 kB changed
+[2024-01-18 03:58:57]: Added : "resources\images\spritesheet_outdoor_1.png" 95 kB
+[2024-01-18 03:58:57]: Added : "resources\images\spritesheet_partybox.png" 1 kB
+[2024-01-18 03:58:57]: Changed: "resources\test.db" 148 kB size, 148 kB changed
+[2024-01-18 03:58:57]: Changed: "states\bag\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\bag\main.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\battle\doSelect.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\battle\enterBattle.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\battle\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\battle\moveSelect.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\choice_select\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\choice_select\main.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\enter_text\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\enter_text\main.lua" 3 kB size, 3 kB changed
+[2024-01-18 03:58:57]: Changed: "states\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\loadsave\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\loadsave\main.lua" 2 kB size, 2 kB changed
+[2024-01-18 03:58:57]: Changed: "states\mapping\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\mapping\main.lua" 3 kB size, 3 kB changed
+[2024-01-18 03:58:57]: Added : "states\partybox" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "states\partybox\init.lua" 1 kB
+[2024-01-18 03:58:57]: Added : "states\partybox\main.lua" 1 kB
+[2024-01-18 03:58:57]: Changed: "states\party\doWhat.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\party\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\party\main.lua" 2 kB size, 2 kB changed
+[2024-01-18 03:58:57]: Changed: "states\party\switch.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\settings\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\settings\main.lua" 3 kB size, 3 kB changed
+[2024-01-18 03:58:57]: Changed: "states\start\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\start\main.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\start_menu\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\start_menu\main.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\world\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\world\main.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\world\option.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\world\pause.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "states\world\text.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Added : "tests" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "tests\chunkloader" 0 kB ,Flags: 64
+[2024-01-18 03:58:57]: Added : "tests\chunkloader\tst.lua" 3 kB
+[2024-01-18 03:58:57]: Changed: "uis\bag.lua" 4 kB size, 4 kB changed
+[2024-01-18 03:58:57]: Changed: "uis\battle.lua" 8 kB size, 8 kB changed
+[2024-01-18 03:58:57]: Changed: "uis\choice_select.lua" 2 kB size, 2 kB changed
+[2024-01-18 03:58:57]: Changed: "uis\enter_text.lua" 5 kB size, 5 kB changed
+[2024-01-18 03:58:57]: Changed: "uis\init.lua" 1 kB size, 1 kB changed
+[2024-01-18 03:58:57]: Changed: "uis\loadsave.lua" 4 kB size, 4 kB changed
+[2024-01-18 03:58:57]: Changed: "uis\mapping.lua" 4 kB size, 4 kB changed
+[2024-01-18 03:58:57]: Changed: "uis\party.lua" 7 kB size, 7 kB changed
+[2024-01-18 03:58:57]: Added : "uis\partybox.lua" 1 kB
+[2024-01-18 03:58:57]: Changed: "uis\settings.lua" 5 kB size, 5 kB changed
+[2024-01-18 03:58:57]: Changed: "uis\start.lua" 4 kB size, 4 kB changed
+[2024-01-18 03:58:57]: Changed: "uis\start_menu.lua" 2 kB size, 2 kB changed
+[2024-01-18 03:58:57]: Changed: "uis\world.lua" 5 kB size, 5 kB changed
+[2024-01-18 03:58:57]: Removed: .cache (0 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats (0 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats\0 (1 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats\1 (1 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats\10 (1 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats\2 (1 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats\3 (1 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats\4 (1 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats\5 (1 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats\6 (1 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats\7 (1 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats\8 (1 kB)
+[2024-01-18 03:58:57]: Removed: .cache\formats\9 (1 kB)
+[2024-01-18 03:58:57]: Removed: .gitignore (1 kB)
+[2024-01-18 03:58:57]: Removed: config (0 kB)
+[2024-01-18 03:58:57]: Removed: config\init.lua (3 kB)
+[2024-01-18 03:58:57]: Removed: config\mappings (0 kB)
+[2024-01-18 03:58:57]: Removed: config\mappings\default_gamepad.lua (1 kB)
+[2024-01-18 03:58:57]: Removed: config\mappings\default_keyboard.lua (1 kB)
+[2024-01-18 03:58:57]: Removed: config\mappings\init.lua (1 kB)
+[2024-01-18 03:58:57]: Removed: extensions\formats (0 kB)
+[2024-01-18 03:58:57]: Removed: extensions\formats\init.lua (1 kB)
+[2024-01-18 03:58:57]: Removed: extensions\libformats.dll (575 kB)
+[2024-01-18 03:58:57]: Removed: extensions\n2de.exe (628 kB)
+[2024-01-18 03:58:57]: Removed: lua53.dll (279 kB)
+[2024-01-18 03:58:57]: Removed: map_configs\mapeditor_config.lua (4 kB)
+[2024-01-18 03:58:57]: Removed: modules\ui_mt.lua (19 kB)
+[2024-01-18 03:58:57]: Removed: terminal.lua (5 kB)
+[2024-01-18 03:58:57]: Summary: 71 files added, 68 files changed, 28 files removed
+[2024-01-18 03:58:57]: Uploading new manifest to 208.64.201.182:80 (handle 11931383876820588005, 34490 bytes).
+[2024-01-18 03:58:58]: Uploading 38 out of 38 missing chunks.
+[2024-01-18 03:59:00]: Success! New manifestID 4648740560032500941 created and 38 new chunks uploaded.
--- /dev/null
+"depotbuild"
+{
+ "appid" "2762580"
+ "depotid" "2762581"
+ "flags" "0"
+ "steamid" "76561198048577880"
+ "manifest" "4648740560032500941"
+ "baselinemanifest" "4792084950510594223"
+}
--- /dev/null
+[2024-01-02 20:31:49]: Starting build for depot 2762582, content path is "/home/nyquist/Development/github/clonemon/steam/ContentBuilder/content/", build flags 0x0
+[2024-01-02 20:31:49]: Building file listing for depot 2762582 ...
+[2024-01-02 20:31:49]: Found 193 files for mapping: /home/nyquist/Development/github/clonemon/steam/ContentBuilder/content/steamdeck * -> .
+[2024-01-02 20:31:49]: Found 193 files (137 MB) for depot 2762582
+[2024-01-02 20:31:49]: Building depot 2762582, baseline manifest 5027810996746026268 (193 files)
+[2024-01-02 20:31:50]: Found 267 chunks ( 268 used previously ) for depot 2762582, took 0 minutes, 0 seconds
+[2024-01-02 20:31:50]: Changes to baseline manifest 5027810996746026268 :
+[2024-01-02 20:31:50]: Changed: "config\init.lua" 1 kB size, 1 kB changed
+[2024-01-02 20:31:50]: Changed: "init.lua" 7 kB size, 7 kB changed
+[2024-01-02 20:31:50]: Changed: "n2de.exe" 626 kB size, 626 kB changed
+[2024-01-02 20:31:50]: Added : "test.db" 0 kB
+[2024-01-02 20:31:50]: Removed: resources\test.db (124 kB)
+[2024-01-02 20:31:50]: Summary: 1 files added, 3 files changed, 1 files removed
+[2024-01-02 20:31:50]: Uploading new manifest to 208.64.201.182:80 (handle 17745443725001411915, 25986 bytes).
+[2024-01-02 20:31:50]: Success! New manifestID 251304651669591706 created and 0 new chunks uploaded.
--- /dev/null
+"depotbuild"
+{
+ "appid" "2762580"
+ "depotid" "2762582"
+ "flags" "0"
+ "steamid" "76561198048577880"
+ "manifest" "251304651669591706"
+ "baselinemanifest" "5027810996746026268"
+}
--- /dev/null
+[2024-01-02 18:09:34]: Starting build for depot 2762583, content path is "/home/nyquist/Development/github/clonemon/steam/ContentBuilder/content/", build flags 0x0
+[2024-01-02 18:09:34]: Building file listing for depot 2762583 ...
+[2024-01-02 18:09:34]: Found 0 files for mapping: /home/nyquist/Development/github/clonemon/steam/ContentBuilder/content steamdeck -> .
+[2024-01-02 18:09:34]: Adding empty folder for empty depot 2762583
+[2024-01-02 18:09:34]: ERROR! Failed to initialize build on server (Access Denied)
--- /dev/null
+run_build.bat shows how to run a Steam content build for AppID 1000 which has one depot 1001.\r
--- /dev/null
+builder\steamcmd.exe +login account password +run_app_build ..\scripts\simple_app_build.vdf +quit\r
--- /dev/null
+"AppBuild"
+{
+ "AppID" "2762580" // Your AppID
+ "Desc" "optimized"
+ "Preview" "0" // make this a preview build only, nothing is uploaded
+ // "Local" "..\..\ContentServer\htdocs" // put content on local content server instead of uploading to Steam
+ "Local" ""
+ "SetLive" "" // set this build live on beta branch AlphaTest
+ "ContentRoot" "..\content\" // content root folder relative to this script file
+ "BuildOutput" "..\output\" // put build cache and log files on different drive for better performance
+ "Depots"
+ {
+ // file mapping instructions for each depot are in separate script files
+ "2762581" "depot_build_2762581.vdf"
+ // "2762582" "depot_build_2762582.vdf"
+ }
+}
--- /dev/null
+"DepotBuild"\r
+{\r
+ "DepotID" "1002"\r
+\r
+ "ContentRoot" "D:\content\depot1002" // override ContentRoot from app build script\r
+\r
+ "FileMapping"\r
+ {\r
+ // all source files and folders in ".\bin" will be mapped into folder ".\executables" in depot\r
+ "LocalPath" "bin\*"\r
+ "DepotPath" "executables\"\r
+ "Recursive" "1" // include all subfolders\r
+ }\r
+\r
+ "FileMapping"\r
+ {\r
+ // override audio files in \\audio with German versions\r
+ "LocalPath" "localization\german\audio\*"\r
+ "DepotPath" "audio\"\r
+ }\r
+\r
+ "FileMapping"\r
+ {\r
+ // copy install script for german version into depot root folder\r
+ "LocalPath" "localization\german\german_installscript.vdf"\r
+ "DepotPath" "."\r
+ }\r
+\r
+ "FileExclusion" "bin\server.exe" // exclude this file\r
+ "FileExclusion" "*.pdb" // exclude all .PDB files everywhere\r
+ "FileExclusion" "bin\tools*" // exclude all files under bin/tools/\r
+\r
+ "InstallScript" "localization\german\german_installscript.vdf"\r
+\r
+ "FileProperties"\r
+ {\r
+ "LocalPath" "bin\setup.cfg"\r
+ "Attributes" "userconfig" // this file will be modified during runtime\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+"DepotBuild"\r
+{\r
+ // Set your assigned depot ID here\r
+ "DepotID" "2762581"\r
+\r
+ // include all files recursivley\r
+ "FileMapping"\r
+ {\r
+ // This can be a full path, or a path relative to ContentRoot\r
+ "LocalPath" ".\windows\*"\r
+\r
+ // This is a path relative to the install folder of your game\r
+ "DepotPath" "."\r
+ \r
+ // If LocalPath contains wildcards, setting this means that all\r
+ // matching files within subdirectories of LocalPath will also\r
+ // be included.\r
+ "Recursive" "1"\r
+ }\r
+}\r
--- /dev/null
+"DepotBuild"\r
+{\r
+ // Set your assigned depot ID here\r
+ "DepotID" "2762582"\r
+\r
+ // include all files recursivley\r
+ "FileMapping"\r
+ {\r
+ // This can be a full path, or a path relative to ContentRoot\r
+ "LocalPath" ".\steamdeck\*"\r
+\r
+ // This is a path relative to the install folder of your game\r
+ "DepotPath" "."\r
+ \r
+ // If LocalPath contains wildcards, setting this means that all\r
+ // matching files within subdirectories of LocalPath will also\r
+ // be included.\r
+ "Recursive" "1"\r
+ }\r
+}\r
--- /dev/null
+"AppBuild"\r
+{\r
+ "AppID" "1000" // your AppID\r
+ "Desc" "This is a simple build script" // internal description for this build\r
+\r
+ "ContentRoot" "..\content\" // root content folder, relative to location of this file\r
+ "BuildOutput" "..\output\" // build output folder for build logs and build cache files\r
+\r
+ "Depots"\r
+ {\r
+ "1001" // your DepotID\r
+ {\r
+ "FileMapping"\r
+ {\r
+ "LocalPath" "*" // all files from contentroot folder\r
+ "DepotPath" "." // mapped into the root of the depot\r
+ "recursive" "1" // include all subfolders\r
+ }\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+local chunkLoader <const> = {}
+local boundries <const> = {}
+local LEFT <const> = 0
+local RIGHT <const> = 1
+local TOP <const> = 2
+local BOTTOM <const> = 3
+local stack <const> = {}
+
+function chunkLoader:addBoundries(boundries)
+ self.boundries = boundries
+end
+
+function chunkLoader:goRight(x, p)
+ -- local p = false
+
+ -- for i, v in pairs(stack) do
+ -- p = v == LEFT
+ -- if p then
+ -- table.remove(stack, i)
+ -- end
+ -- end
+
+ local v = p and (.5 * (x - 1)) or (2 * x + 3)
+
+ v = math.floor(v)
+ local bmax = self.boundries.right.max
+ local bmin = self.boundries.right.min
+
+ if (v > bmax) and (v < bmin) then
+ return nil
+ end
+ table.insert(stack, RIGHT)
+ return v
+end
+
+function chunkLoader:goLeft(x, p)
+ -- local p = false
+
+ -- for i, v in pairs(stack) do
+ -- p = v == RIGHT
+ -- if p then
+ -- table.remove(stack, i)
+ -- end
+ -- end
+ local v = p and (.5 * (x - 3)) or (2 * x + 1)
+ v = math.floor(v)
+ local bmax = self.boundries.left.max
+ local bmin = self.boundries.left.min
+
+ if (v > bmax) and (v < bmin) then
+ return nil
+ end
+ table.insert(stack, LEFT)
+ return v
+end
+
+function chunkLoader:goTop(x, p)
+ -- local p = false
+
+ -- for i, v in pairs(stack) do
+ -- p = v == BOTTOM
+ -- if p then
+ -- table.remove(stack, i)
+ -- end
+ -- end
+ local v = p and (.5 * (x - 2)) or (2 * x + 4)
+ v = math.floor(v)
+ local bmax = self.boundries.top.max
+ local bmin = self.boundries.top.min
+
+ if (v > bmax) and (v < bmin) then
+ return nil
+ end
+ table.insert(stack, TOP)
+ return v
+end
+
+function chunkLoader:goBottom(x, p)
+ -- local p = false
+
+ -- for i, v in pairs(stack) do
+ -- p = v == TOP
+ -- if p then
+ -- table.remove(stack, i)
+ -- end
+ -- end
+ local v = p and (.5 * (x - 4)) or (2 * x + 2)
+ v = math.floor(v)
+ local bmax = self.boundries.bottom.max
+ local bmin = self.boundries.bottom.min
+
+ if (v > bmax) and (v < bmin) then
+ return nil
+ end
+ table.insert(stack, BOTTOM)
+ return v
+end
+
+chunkLoader:addBoundries({
+ left = {max = 200, min = 0},
+ right = {max = 200, min = 0},
+ top = {max = 200, min = 0},
+ bottom = {max = 200, min = 0},
+})
+
+-- local id = 20
+-- local id = chunkLoader:goBottom(id)
+-- print(id)
+-- local id = chunkLoader:goBottom(id)
+-- print(id)
+-- local id = chunkLoader:goBottom(id)
+-- print(id)
+-- local id = chunkLoader:goTop(id)
+-- print(id)
+-- local id = chunkLoader:goTop(id)
+-- print(id)
+-- local id = chunkLoader:goTop(id)
+-- print(id)
+--
+local id = 20
+print(id)
+local id = chunkLoader:goTop(id)
+print(id)
+local id = chunkLoader:goTop(id)
+print(id)
+local id = chunkLoader:goRight(id)
+print(id)
+local id = chunkLoader:goRight(id)
+print(id)
+local id = chunkLoader:goBottom(id, true)
+print(id)
+local id = chunkLoader:goBottom(id, true)
+print(id)
+local id = chunkLoader:goLeft(id, true)
+print(id)
+local id = chunkLoader:goLeft(id, true)
+print(id)
--- /dev/null
+local assign = require("extensions.metatables.ui")
+local vars <const> = {}
+local ui, ui_mt = assign("bag", {vars = vars})
+
+function ui:init(window_size, options)
+ ui_mt:_init(nil, window_size, "NotoSansMono-Regular.ttf", 8, options, function()
+ vars.line_count = 7
+ vars.description_line_ids = {}
+ end)
+end
+
+function ui:startCallback()
+ nyq.hasFrameCap(false)
+ vars.selection_rect = ui:createRect({r = 100, g = 0, b = 0, a = 50}, true, 6)
+ vars.selected = 1
+ vars.types = {}
+ local i = 1
+ for k, v in pairs(params) do
+ vars.types[i] = k
+ i = i + 1
+ vars[k] = {
+ text_ids = {},
+ description_lines = {}
+ }
+ end
+ vars.type_selected = 1
+ vars.type_section_max = #vars.types
+
+ vars.type_selected = 1
+ for i = 1, vars.line_count do
+ ui:addText2(
+ vars.description_line_ids,
+ i,
+ "description", -- blank string here causes crashing
+ 5,
+ {r = 0, g = 0, b = 0, a = 255},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+ end
+
+ ui:addBackgroundImage("gradient", "gradient.png")
+ ui:setBackgroundImage("gradient")
+ vars.bag_id = ui:imageCreate("bag.png", 1)
+
+ for _, type in pairs(vars.types) do
+ ui:addText("label", type, type, 5,
+ {r = 0, g = 0, b = 0, a = 150},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+ for i, item in pairs(params[type]) do
+ vars[type].text_ids[i] = {}
+ ui:addText2(vars[type].text_ids[i], "name", item.name, 5,
+ {r = 0, g = 0, b = 0, a = 150},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+ vars[type].description_lines[i] = {}
+ vars[type].description_lines[i] = string.WordWrap(item.description, 20)
+ ui:addText2(vars[type].text_ids[i], "quantity", string.format("x%d", item.quantity), 5,
+ {r = 0, g = 0, b = 0, a = 150},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+ end
+ end
+end
+
+function ui:update()
+ local type = vars.types[vars.type_selected]
+ ui:updateBackground()
+ ui:imageUpdate(vars.bag_id, {x = 0, y = 0}, {w = ui.window_size.w, h = ui.window_size.h})
+ local itembox_width = 118
+ local padding = 2
+ local size = ui:getTextSize("label", type)
+ if nyq.getTicks() % 600 <= 300 then
+ ui:updateMenuItem("transparent_arrow_left", 1, {
+ x = 7,
+ y = 8
+ })
+ ui:updateMenuItem("transparent_arrow_right", 1, {
+ x = 107,
+ y = 8
+ })
+ end
+ ui:updateText("label", type, {
+ x = padding + (itembox_width / 2) - (size.w / 2), y = 6
+ })
+
+ local ys = {}
+ for i, item in pairs(vars[type].text_ids) do
+ local y = 18 + ((i - 1) * (ui.font_size + 1))
+ ys[i] = y + 1
+ ui:updateText2(vars[type].text_ids[i], "name", {
+ x = 130, y = y
+ })
+ ui:updateText2(vars[type].text_ids[i], "quantity", {
+ x = 210, y = y
+ })
+ end
+ local size = ui:getTextSize2(vars[type].text_ids[vars.selected], "name")
+ vars.selection_max = #vars[type].text_ids
+ ui:rectUpdate(vars.selection_rect,
+ {x = 130,
+ y = ys[vars.selected]},
+ {w = 99,
+ h = ui.font_size + 2})
+
+
+ for i, line in pairs(vars[type].description_lines[vars.selected]) do
+ ui:textChange2(vars.description_line_ids, i, line,
+ {r = 0, g = 0, b = 0, a = 150},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+ local y = 74 + ((i - 1) * (ui.font_size + 1))
+ ui:updateText2(vars.description_line_ids, i, {
+ x = 8, y = y
+ })
+ end
+end
+
+return ui
--- /dev/null
+local assign = require("extensions.metatables.ui")
+local vars <const> = {}
+local ui, ui_mt = assign("battle", {vars = vars})
+
+function ui:init(spritesheet, window_size, options)
+ ui_mt:_init(spritesheet, window_size, "NotoSansMono-Regular.ttf", 8, options, function()
+ vars.narration = {}
+ vars.narration.fg_color = {r = 255, g = 255, b = 255, a = 255}
+ vars.narration.bg_color = {r = 255, g = 255, b = 255, a = 0}
+ vars.current_pokemon = ""
+ vars.move_select = {}
+ vars.move_select.moves = {}
+ vars.move_select.pp = {}
+ vars.move_select.pp.position = {x = 170, y = 133}
+ vars.move_select.type = {}
+ vars.move_select.type.position = {x = 170, y = 145}
+ vars.line_count = 2
+ vars.line_ids = {}
+
+ local positions = {
+ [1] = {x = 12, y = 133},
+ [2] = {x = 82, y = 133},
+ [3] = {x = 12, y = 145},
+ [4] = {x = 82, y = 145}
+ }
+
+ for i = 1, #positions do
+ vars.move_select.moves[i] = {}
+ vars.move_select.moves[i].string = nil
+ vars.move_select.moves[i].position = positions[i]
+ vars.move_select.moves[i].pp_id = nil
+ vars.move_select.moves[i].name_id = nil
+ vars.move_select.moves[i].type_id = nil
+ end
+ vars.text_box = {}
+ vars.text_box.position = {x = 0, y = 130}
+ vars.triggered_song = false
+
+
+ vars.formats = {}
+ vars.formats.clonemon_enter = "A Wild Clonemon has appeared"
+ vars.formats.enter_battle = "%s entered the battle"
+ vars.formats.lose = "you lost"
+ vars.formats.lose_money = "you get %d for winning"
+ vars.formats.doWhat = "what will %s do?"
+ vars.selected = 1
+ end)
+
+end
+
+
+function ui:startCallback()
+ nyq.hasFrameCap(true)
+ vars.menu_items_id = ui:newSprite("menu_items.png")
+ ui:linesCreate("narration", 3, vars.narration.fg_color, vars.narration.bg_color)
+ ui:spriteAddCrops(vars.menu_items_id, "selection arrow", 6, {
+ {
+ x = 7,
+ y = 0,
+ w = 7,
+ h = 7
+ }
+ })
+ ui:addCrop("my_health",
+ {x = 0, y = 30, w = 100, h = 28},
+ {w = 100, h = 28}
+ )
+ ui:addCrop("doWhat",
+ {x = 100, y = 28, w = 85, h = 30},
+ {w = 85, h = 30}
+ )
+
+ vars.narration.background_rect_id = ui:createRect({r = 0, g = 0, b = 0, a = 200}, true, 4)
+ ui:addCrop("move_select",
+ {x = 0, y = 0, w = 240, h = 30},
+ {w = 240, h = 30}
+ )
+ ui:addBackgroundImage("grassland", "clonemon_battle_grass.png")
+ ui:setBackgroundImage("grassland")
+
+ local format = vars.formats.enter_battle
+ local str = string.format(format, params.rivals_pokemon[1].name)
+
+ ui:addText("narration", "enter_battle", str, 5, vars.narration.fg_color, vars.narration.bg_color)
+
+ local fg_color = {r = 0, g = 0, b = 0, a = 255}
+ local bg_color = {r = 0, g = 0, b = 0, a = 0}
+ ui:addText("pokemon", "name", params.my_pokemon.name, 5, fg_color, bg_color)
+ ui:addText("pokemon", "level", params.my_pokemon.level, 5, {r = 0, g = 0, b = 0, a = 255},
+ {r = 0, g = 0, b = 0, a = 0})
+ format = vars.formats.doWhat
+ str = string.format(format, params.player.name)
+
+ ui:addText("do_narration", "narration", str, 5, vars.narration.fg_color,
+ vars.narration.bg_color)
+
+ vars.do_options = {}
+ for i = 1, 4 do
+ vars.do_options[i] = {}
+ end
+ vars.do_options[1].position = {x = 167, y = 132}
+ vars.do_options[2].position = {x = 220, y = 132}
+ vars.do_options[3].position = {x = 167, y = 132 + ui.font_size + 1}
+ vars.do_options[4].position = {x = 220, y = 132 + ui.font_size + 1}
+ ui:addText2(vars.do_options[1], "id", "fight", 6, fg_color, bg_color)
+ ui:addText2(vars.do_options[2], "id", "bag", 6, fg_color, bg_color)
+ ui:addText2(vars.do_options[3], "id", "clonemon", 6, fg_color, bg_color)
+ ui:addText2(vars.do_options[4], "id", "run", 6, fg_color, bg_color)
+
+ local fg_color = {r = 0, g = 0, b = 0, a = 0}
+ local bg_color = {r = 255, g = 255, b = 255, a = 0}
+
+ for i, move in ipairs(vars.move_select.moves) do
+ ui:addText2(move, "name_id", params.my_pokemon.moves[i].name, 5, fg_color, bg_color)
+
+ str = string.format("pp %s/%s", params.my_pokemon.moves[i].pp.remaining,
+ params.my_pokemon.moves[i].pp.total)
+
+ ui:addText2(move, "pp_id", str, 5, fg_color, bg_color)
+
+ str = string.format("%s", params.my_pokemon.moves[i].type)
+
+ ui:addText2(move, "type_id", str, 5, fg_color, bg_color)
+ end
+ Ex.Audio.init({
+ battle = {file = "battle1.wav", loop = -1},
+ })
+ Ex.Audio.play("battle")
+end
+
+function ui:updateMyHealth()
+ ui:updateCrop("my_health", {x = 139, y = 90})
+ ui:updateText("pokemon", "name", {x = 140, y = 90})
+ ui:updateText("pokemon", "level", {x = 223, y = 90})
+end
+
+
+function ui:updateNarration(type, text)
+ ui:rectUpdate(vars.narration.background_rect_id, vars.text_box.position, {w = 240, h = 30})
+
+ local position = Copy.shallow_copy(vars.text_box.position)
+ position.x = position.x + 4
+ position.y = position.y + 0
+
+ -- need worldwrap
+ if type == "enter_battle" then
+ vars.narration.pages = 1
+ ui:updateText("narration", "enter_battle", position)
+ elseif type == "custom" then
+ ui:linesDraw("narration", text, 48, position)
+ end
+end
+
+function ui:updateDo()
+ ui:rectUpdate(vars.narration.background_rect_id, vars.text_box.position, {w = 155, h = 30})
+ ui:updateCrop("doWhat", {x = 155, y = 130})
+ ui:updateText("do_narration", "narration", {x = 4, y = 130})
+
+ for i = 1, 4 do
+ ui:updateText2(vars.do_options[i], "id", vars.do_options[i].position)
+ end
+
+ local size = ui:getTextSize2(vars.do_options[vars.selected], "id")
+ local text_pos = vars.do_options[vars.selected].position
+
+ ui:spriteUpdateCrop(vars.menu_items_id, "selection arrow", 1, {
+ x = text_pos.x - 8 , y = text_pos.y + 2
+ })
+end
+
+function ui:addMoves(moves)
+ local fg_color = {r = 0, g = 0, b = 0, a = 0}
+ local bg_color = {r = 255, g = 255, b = 255, a = 0}
+
+ for i, move in ipairs(vars.move_select.moves) do
+ str = string.format("pp %s/%s", moves[i].pp.remaining,
+ moves[i].pp.total)
+ str = string.format("%s", moves[i].type)
+ end
+end
+
+function ui:updateMoveSelect()
+
+ ui:updateCrop("move_select", vars.text_box.position)
+
+ for i, move in ipairs(vars.move_select.moves) do
+ ui:updateText2(move, "name_id", move.position)
+ end
+
+ move = vars.move_select.moves[vars.selected]
+ ui:updateText2(move, "pp_id", vars.move_select.pp.position)
+ ui:updateText2(move, "type_id", vars.move_select.type.position)
+
+ local size = ui:getTextSize2(vars.move_select.moves[vars.selected], "name_id")
+ local text_pos = vars.move_select.moves[vars.selected].position
+
+ ui:spriteUpdateCrop(vars.menu_items_id, "selection arrow", 1, {
+ x = text_pos.x - 8 , y = text_pos.y + 2
+ })
+
+end
+
+return ui
--- /dev/null
+local assign = require("extensions.metatables.ui")
+local vars <const> = {}
+local ui, ui_mt = assign("choice_select", {vars = vars})
+
+function ui:init(window_size, options)
+ ui_mt:_init(nil, window_size, "NotoSansMono-Regular.ttf", 8, options, function()
+ vars.sprite_ids = {}
+ vars.unselected_rect_ids = {}
+ vars.selected = 1
+ end)
+end
+
+function ui:startCallback()
+ nyq.hasFrameCap(false)
+ ui:addBackgroundImage("background", "gradient.png")
+ ui:setBackgroundImage("background")
+
+ vars.max = params.count
+
+ for i = 1, vars.max do
+ local w = (ui.window_size.w / vars.max)
+ local x = (i - 1) * w
+ vars.sprite_ids[i] = ui:newSprite(params.sprite)
+ vars.unselected_rect_ids[i] = ui:createRect({r = 0, g = 0, b = 0, a = 200}, true, 2)
+ ui:spriteAddCrops(vars.sprite_ids[i], "choices", 0, { {
+ x = x,
+ y = 0,
+ w = w,
+ h = ui.window_size.h
+ } })
+ end
+end
+
+function ui:update()
+ ui:updateBackground()
+
+ for i = 1, vars.max do
+ local w = (ui.window_size.w / vars.max)
+ local x = (i - 1) * w
+ if i ~= vars.selected then
+ ui:rectUpdate(vars.unselected_rect_ids[i], {
+ x = x,
+ y = 0,
+ }, {
+ w = w,
+ h = ui.window_size.h
+ })
+ end
+ ui:spriteUpdateCrop(vars.sprite_ids[i], "choices", 1, {x = x, y = 0})
+ end
+end
+
+return ui
--- /dev/null
+local assign = require("extensions.metatables.ui")
+local vars <const> = {}
+local ui, ui_mt = assign("enter_text", {vars = vars})
+
+function ui:init(window_size, options)
+ ui_mt:_init(nil, window_size, "NotoSansMono-Regular.ttf", 8, options, function()
+ vars.string_id = {}
+ vars.line_count = 5
+ vars.character_length = 46
+ vars.string = ""
+ vars.full = false
+ vars. rect_position = {y = 0, x = 0}
+ vars.input = {}
+ vars.character_limit = nil
+ vars.clonemon_image_id = nil
+ vars.title = nil
+ end)
+end
+
+
+function ui:startCallback()
+ nyq.hasFrameCap(false)
+ ui:addBackgroundImage("background", "clonemon_battle_grass.png")
+ ui:setBackgroundImage("background")
+ vars.rect_id = ui:createRect({r = 0, g = 0, b = 0, a = 180}, true, 0)
+ vars.blinker = ui:createRect({r = 255, g = 255, b = 255, a = 255}, true, 0)
+ vars.clonemon_image_id = ui:newSprite(params.sprite)
+ vars.string = ""
+ ui:spriteAddCrops(vars.clonemon_image_id, "clonemon", 0, {
+ {x = 105, y = 0, w = 91 , h = 62}
+ })
+ local fg_color = {r = 0, g = 0, b = 0, a = 0}
+ local bg_color = {r = 255, g = 255, b = 255, a = 0}
+ vars.character_limit = params.character_limit
+ vars.title = params.title
+ vars.cursor = 0
+ if vars.title then
+ ui:addText("text", "input", vars.title, 5, {r = 0, g = 0, b = 0, a = 0},
+ {r = 0, g = 0, b = 0, a = 0})
+ end
+ vars.line_count = 1
+
+ if (Ex.Config.controller == "none") then
+ vars.rect_position.x = 0
+ vars.rect_position.y = 115
+ else
+ vars.rect_position.x = 0
+ vars.rect_position.y = 80
+ vars.keyboard_upper_id = ui:imageCreate("keyboard_upper.png", 1)
+ vars.keyboard_lower_id = ui:imageCreate("keyboard_lower.png", 1)
+ vars.key_selector_id = ui:createRect({r = 255, g = 255, b = 255, a = 100}, true, 2)
+ vars.keyboard_background__id = ui:createRect({r = 51, g = 51, b = 51, a = 200}, true, 0)
+ vars.isUpper = false
+ vars.key_change_case = "\n"
+ vars.key_backspace = "\b"
+ vars.key_done = "\z"
+ vars.letter_selection = {
+ "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", " ",
+ "a", "s", "d", "f", "g", "h", "j", "k", "l", " ", vars.key_backspace,
+ "z", "x", "c", "v", "b", "n", "m", " ",vars.key_change_case, vars.key_done, vars.key_done,
+ }
+ end
+ vars.rect_size = {w = 91 , h = 11}
+
+ ui:addText2(
+ vars.string_id,
+ "line",
+ "Enter Name", -- blank string here causes crashing
+ 5,
+ {r = 0, g = 0, b = 0, a = 255},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+end
+
+function ui:update()
+ ui:updateBackground()
+ local title_offset = 0
+ local text_offset = 0
+ local title_size = nil
+ if vars.title then
+ title_size = ui:getTextSize("text", "input")
+ text_offset = (ui.window_size.w / 2) - (((vars.rect_size.w) - (title_size.w)) / 2)
+ title_offset = text_offset - (title_size.w)
+ ui:updateText("text", "input", { x = title_offset, y = vars.rect_position.y})
+ end
+
+ ui:rectUpdate(vars.rect_id, {x = vars.rect_position.x + (text_offset), y = vars.rect_position.y},
+ vars.rect_size)
+
+ local position = nil
+ local y = ((vars.rect_position.y) - (1))
+ if (Ex.Config.controller == "none") then
+ position = {
+ x = ui.window_size.w / 2 - (91 / 2),
+ y = 30
+ }
+ else
+ local cx = vars.cursor % 11
+ local cy = math.floor(vars.cursor / 11)
+ if vars.isUpper then
+ ui:imageUpdate(vars.keyboard_upper_id, {x = 4, y = 98}, {w = 230, h = 59})
+ else
+ ui:imageUpdate(vars.keyboard_lower_id, {x = 4, y = 98}, {w = 230, h = 59})
+ end
+ local w = 23
+ if vars.letter_selection[vars.cursor + 1] == vars.key_done then
+ w = 44
+ if vars.cursor == 32 then
+ cx = cx - 1
+ end
+ end
+ ui:rectUpdate(vars.key_selector_id, {x = 3 + (21 * cx), y = 97 + (20 * cy)},
+ {w = w , h = 21})
+ ui:rectUpdate(vars.keyboard_background__id, {x = 3, y = 97},
+ {w = 233 , h = 61})
+ position = {
+ x = ui.window_size.w / 2 - (91 / 2),
+ y = 9
+ }
+ end
+
+ ui:spriteUpdateCrop(vars.clonemon_image_id, "clonemon", 1, position)
+
+ if string.len(vars.string) == 0 then
+ if nyq.getTicks() % 600 <= 300 then
+ ui:rectUpdate(vars.blinker, {x = 3 + text_offset + vars.rect_position.x, y = y + 2},
+ {w = (ui.font_size) / 4, h = (ui.font_size )})
+ end
+ return
+ end
+
+
+ local strlen = string.len(vars.string)
+ if strlen >= vars.character_length then
+ vars.full = true
+ end
+
+ if not (strlen > 0) then return end
+
+ ui:textChange2(
+ vars.string_id,
+ "line",
+ vars.string,
+ {r = 255, g = 255, b = 255, a = 255},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+
+ local x = 3 + text_offset + vars.rect_position.x
+ ui:updateText2(vars.string_id, "line",
+ {x = x, y = y }
+ )
+ local size = ui:getTextSize2(vars.string_id, "line")
+
+ if not vars.full then
+ local position = {x = x + size.w, y = y + 2}
+ local size = {w = (ui.font_size) / 4, h = (ui.font_size)}
+ if nyq.getTicks() % 600 <= 300 then
+ if strlen < vars.character_length then
+ ui:rectUpdate(vars.blinker, position, size)
+
+ elseif(i + 1 <= vars.line_count) then
+ ui:rectUpdate(vars.blinker, position, size)
+ end
+ end
+ end
+
+
+end
+
+return ui
--- /dev/null
+uis = {}
+uis.start = require("uis.start")
+uis.world = require("uis.world")
+uis.battle = require("uis.battle")
+uis.loadsave = require("uis.loadsave")
+uis.enter_text = require("uis.enter_text")
+uis.choice_select = require("uis.choice_select")
+uis.party = require("uis.party")
+uis.bag = require("uis.bag")
+uis.start_menu = require("uis.start_menu")
+uis.settings = require("uis.settings")
+uis.mapping = require("uis.mapping")
+uis.partybox = require("uis.partybox")
--- /dev/null
+local assign = require("extensions.metatables.ui")
+local vars <const> = {
+ players = {},
+ selected = 1,
+ selected2 = 1,
+ menu_size = 2
+
+}
+local ui, ui_mt = assign("loadsave", vars)
+
+function ui:init(spritesheet, window_size, options)
+ ui_mt:_init(spritesheet, window_size, "NotoSansMono-Regular.ttf", 8, options, function()
+ end)
+end
+
+function ui:startCallback()
+ local fg_color = {r = 0, g = 0, b = 0, a = 0}
+ local bg_color = {r = 255, g = 255, b = 255, a = 0}
+ ui:addCrop("load_selected",
+ {x = 0, y = 0, w = 208, h = 80},
+ {w = 208, h = 80}
+ )
+ ui:addCrop("box1_unselected",
+ {x = 208, y = 0, w = 208, h = 80},
+ {w = 208, h = 80}
+ )
+
+ ui:addCrop("box2_selected",
+ {x = 0, y = 80, w = 208, h = 32},
+ {w = 208, h = 32}
+ )
+ ui:addCrop("box2_unselected",
+ {x = 208, y = 80, w = 208, h = 32},
+ {w = 208, h = 32}
+ )
+ ui:addCrop("right_arrow",
+ {x = 416, y = 0, w = 22, h = 27},
+ {w = 22, h = 27}
+ )
+ ui:addCrop("left_arrow",
+ {x = 416, y = 27, w = 22, h = 27},
+ {w = 22, h = 27}
+ )
+ ui:addBackgroundImage("gradient", "gradient.png")
+ ui:setBackgroundImage("gradient")
+ if players then
+ for i, v in pairs(players) do
+ ui.players[i] = {}
+ for k2, v2 in pairs(v) do
+ if k2 == "person_id" then
+ person = Ex.Database.getFromID("people", v2);
+ local str = string.format("name: %s", person.name)
+ ui:addText2(ui.players[i], "name_id", str, 5, fg_color, bg_color)
+ local str = string.format("age: %d", person.age)
+ ui:addText2(ui.players[i], "age_id", str, 5, fg_color, bg_color)
+ end
+
+ end
+ end
+ end
+ ui:addText("menu", "new_game", "new game", 5, fg_color, bg_color)
+end
+
+function ui:update()
+ nyq.hasFrameCap(true)
+ ui:updateBackground()
+
+ if players and #players > 0 then
+ if ui.selected == 1 then
+ ui:updateCrop("load_selected", {x = 16, y = 8})
+ ui:updateCrop("box2_unselected", {x = 16, y = 96})
+ elseif ui.selected == 2 then
+ ui:updateCrop("box1_unselected", {x = 16, y = 8})
+ ui:updateCrop("box2_selected", {x = 16, y = 96})
+ end
+ if (ui.selected2 < #players) then
+ if (nyq.getTicks() % 800 < 400) then
+ ui:updateCrop("right_arrow", {x = 215, y = 30}, {w = 22 * ui.scale, h = 27 * ui.scale})
+ end
+ end
+ if (ui.selected2 > 1) then
+ if (nyq.getTicks() % 800 < 400) then
+ ui:updateCrop("left_arrow", {x = 3, y = 30}, {w = 22 * ui.scale, h = 27 * ui.scale})
+ end
+ end
+ ui:updateText2(ui.players[ui.selected2], "name_id", {x = 22, y = 10})
+ ui:updateText2(ui.players[ui.selected2], "age_id", {x = 22, y = 20})
+ ui:updateText("menu", "new_game", {x = 22, y = 105})
+ else
+ ui:updateCrop("box2_selected", {x = 16, y = 8})
+ ui:updateText("menu", "new_game", {x = 22, y = 18})
+ end
+
+
+end
+
+return ui
--- /dev/null
+local assign = require("extensions.metatables.ui")
+local vars <const> = {}
+local ui, ui_mt = assign("mapping", {vars = vars})
+
+function ui:init(window_size, options)
+ ui_mt:_init(nil, window_size, "NotoSansMono-Regular.ttf", 6, options, function()
+ end)
+end
+
+function ui:setOptions(name)
+ local fg_color_selected = {r = 255, g = 255, b = 255, a = 0}
+ local bg_color = {r = 0, g = 0, b = 0, a = 0}
+ local fg_color = {r = 128, g = 128, b = 128, a = 0}
+ local i = 1
+ vars.restart_required = false
+ for k, v in pairs(vars.temp_settings) do
+ if v.key ~= Ex.Config.mappings[params.type][k].key then
+ vars.restart_required = true
+ end
+ vars.select_options[i] = {
+ name = k,
+ value = v.key
+ }
+ i = i + 1
+ end
+ vars.select_options[i] = {name = "clear"}
+ i = i + 1
+ vars.select_options[i] = {name = "apply"}
+ i = i + 1
+ vars.select_options[i] = {name = "go back"}
+
+ vars.selection_max = i
+ local max_width = 0
+
+ for k, v in pairs(vars.select_options) do
+
+ if v.value then
+ local color = fg_color_selected
+ if v.name == name then
+ v.value = "enter input"
+ color = {r = 255, g = 0, b = 0, a = 0}
+ end
+ local total_length = 20
+ local str = v.name .. ":"
+ for j = 0, total_length - string.len(str) do
+ str = str .. " "
+ end
+ str = str .. v.value
+ ui:addText("menu", v.name, str, 1, fg_color, bg_color)
+ ui:addText("menu", v.name .. " selected", str, 1, color, bg_color)
+ else
+ ui:addText("menu", v.name, v.name, 1, fg_color, bg_color)
+ ui:addText("menu", v.name .. " selected", v.name, 1, fg_color_selected, bg_color)
+ end
+
+ local size = ui:getTextSize("menu", v.name .. " selected")
+ if (size.w > max_width) then max_width = size.w end
+ end
+
+ vars.text_center = (unscaled_window_size.w / 2) - (max_width / 2)
+end
+
+function ui:startCallback()
+ vars.selected = 1
+ vars.select_options = {}
+ vars.selection_max = 0
+ vars.text_center = 0
+ vars.states = {"select input", "change input", "apply"}
+ vars.state = "select input"
+ ui:addText("warnings", "restart", "restart required", 1, {r = 255, g = 0, b = 0, a = 150}, {r = 0, g = 0, b = 0, a = 0})
+ vars.restart_required = false
+ vars.temp_settings = Copy.deepcopy(Ex.Config.mappings[params.type])
+ ui:setOptions()
+end
+
+function ui:update()
+ for k, v in pairs(vars.select_options) do
+
+ local y =
+ (unscaled_window_size.h / 2) -
+ ( ((ui.font_size + 1) * vars.selection_max) / 2)
+ + ((ui.font_size + 1) * k)
+
+ local f = v.name
+ if vars.selected == k then
+ f = v.name .. " selected"
+ end
+
+ if not v.value then
+ ui:updateText("menu", f , {x = "center", y = y})
+ else
+ ui:updateText("menu", f , {x = vars.text_center, y = y})
+ end
+
+ if k == vars.selection_max and vars.restart_required then
+ size = ui:getTextSize("warnings", "restart")
+ ui:updateText("warnings", "restart", {x = "center", y = y + ui.font_size + 5})
+ end
+
+
+ end
+ ui:notifyUpdate()
+end
+
+return ui
--- /dev/null
+local assign = require("extensions.metatables.ui")
+local vars <const> = {}
+local ui, ui_mt = assign("party", {vars = vars})
+
+function ui:init(window_size, options)
+ ui_mt:_init(nil, window_size, "NotoSansMono-Regular.ttf", 6, options, function()
+ vars.selected = 1
+ vars.selection_max = 0
+ end)
+end
+
+function ui:startCallback()
+ vars.notSelected_rects = {}
+ vars.selection_max = ui:optionSelectInit({"Summary", "Switch", "Item", "Cancel"})
+
+ local fg_color = {r = 255, g = 255, b = 255, a = 160}
+ local fg_color2 = {r = 0, g = 0, b = 0, a = 255}
+ local bg_color = {r = 0, g = 0, b = 0, a = 0}
+
+ vars.narration = {}
+ ui:addText("narration", "choice", "Choose a Clonemon", 4, fg_color2, bg_color)
+ ui:addText("narration", "back", "go back", 4, fg_color2, bg_color)
+ ui:addText("narration", "do_what", " ", 6, fg_color2, bg_color)
+
+ for i = 1, 7 do
+ vars.notSelected_rects[i] = {}
+ end
+
+ vars.notSelected_rects[1].position = {x = 3, y = 4}
+ vars.notSelected_rects[2].position = {x = 121, y = 4}
+ vars.notSelected_rects[3].position = {x = 3, y = 50}
+ vars.notSelected_rects[4].position = {x = 121, y = 50}
+ vars.notSelected_rects[5].position = {x = 3, y = 96}
+ vars.notSelected_rects[6].position = {x = 121, y = 96}
+ vars.notSelected_rects[7].position = {x = 121, y = 143}
+ vars.clonemon_switch = 0
+
+ vars.clonemon = {}
+
+ for i, clonemon in pairs(my_clonemon) do
+ vars.clonemon[i] = {}
+ vars.clonemon[i].ids = {}
+ ui:addText2(vars.clonemon[i].ids, "name", clonemon.name, 4, fg_color, bg_color)
+ ui:addText2(vars.clonemon[i].ids, "max_hp", clonemon.max_hp, 4, fg_color, bg_color)
+ ui:addText2(vars.clonemon[i].ids, "hp", clonemon.hp, 4, fg_color, bg_color)
+ ui:addText2(vars.clonemon[i].ids, "level", clonemon.level, 4, fg_color, bg_color)
+ end
+
+ for i = 1, 7 do
+ vars.notSelected_rects[i].id = ui:createRect({r = 0, g = 0, b = 0, a = 125}, true, 3)
+ end
+
+ local rect_color = {r = 255, g = 255, b = 255, a = 255}
+
+ vars.narration.rect = {
+ id = ui:createRect(rect_color, true, 3),
+ position = {x = 3, y = 143},
+ size = {w = 116, h = 15}
+ }
+
+ vars.goBack = {
+ id = ui:createRect({r = 102, g = 114, b = 146, a = 255}, true, 3),
+ position = {x = 121, y = 143},
+ size = {w = 116, h = 15}
+ }
+
+ vars.doWhat = {
+ id = ui:createRect(rect_color, true, 5),
+ position = {x = 121, y = 50},
+ size = {w = 116, h = 108}
+ }
+
+ vars.boxes_id = ui:imageCreate("clonemon_party.png", 1)
+ vars.clonemon_selected = 1
+end
+
+function ui:partyUpdate()
+ ui:imageUpdate(vars.boxes_id, {x = 0, y = 0}, {w = ui.window_size.w, h = 140})
+ ui:rectUpdate(vars.narration.rect.id, vars.narration.rect.position, vars.narration.rect.size)
+ ui:rectUpdate(vars.goBack.id, vars.goBack.position, vars.goBack.size)
+ ui:updateText("narration", "choice", {x = 6, y = 146})
+ ui:updateText("narration", "back", {x = 200, y = 146})
+ if my_clonemon then
+ for i, clonemon in pairs(my_clonemon) do
+ local name_pos = {
+ x = vars.notSelected_rects[i].position.x + 4,
+ y = vars.notSelected_rects[i].position.y + 4,
+ }
+ ui:updateText2(vars.clonemon[i].ids, "name", name_pos)
+ end
+ end
+ for i = 1, 6 do
+ if vars.selected ~= i then
+ ui:rectUpdate(vars.notSelected_rects[i].id, vars.notSelected_rects[i].position, {w = 116, h = 44})
+ end
+ end
+ if vars.selected ~= 7 then
+ ui:rectUpdate(vars.notSelected_rects[7].id, vars.notSelected_rects[7].position, {w = 116, h = 15})
+ end
+end
+
+-- TODO:
+-- fix delay in appearing
+function ui:doWhatUpdate()
+ local fg_color2 = {r = 0, g = 0, b = 0, a = 255}
+ local bg_color = {r = 0, g = 0, b = 0, a = 0}
+ ui:imageUpdate(vars.boxes_id, {x = 0, y = 0}, {w = ui.window_size.w, h = 140})
+ ui:rectUpdate(vars.narration.rect.id, vars.narration.rect.position, vars.narration.rect.size)
+ self:optionSelectUpdate(
+ {
+ x = vars.notSelected_rects[vars.clonemon_selected].position.x + 116 - 8,
+ y = vars.notSelected_rects[vars.clonemon_selected].position.y + 22,
+ }
+ , vars.selected)
+ local format = string.format("Do what with %s?", my_clonemon[vars.clonemon_selected].name)
+
+ ui:textChange("narration", "do_what", format , fg_color2, bg_color)
+ ui:updateText("narration", "do_what", {x = 6, y = 146})
+
+ if my_clonemon then
+ for i, clonemon in pairs(my_clonemon) do
+ local name_pos = {
+ x = vars.notSelected_rects[i].position.x + 4,
+ y = vars.notSelected_rects[i].position.y + 4,
+ }
+ ui:updateText2(vars.clonemon[i].ids, "name", name_pos)
+ end
+ end
+ for i = 1, 6 do
+ if vars.clonemon_selected ~= i then
+ ui:rectUpdate(vars.notSelected_rects[i].id, vars.notSelected_rects[i].position, {w = 116, h = 44})
+ end
+ end
+ if vars.clonemon_selected ~= 7 then
+ ui:rectUpdate(vars.notSelected_rects[7].id, vars.notSelected_rects[7].position, {w = 116, h = 15})
+ end
+end
+
+function ui:switchUpdate()
+ local fg_color2 = {r = 0, g = 0, b = 0, a = 255}
+ local bg_color = {r = 0, g = 0, b = 0, a = 0}
+ ui:imageUpdate(vars.boxes_id, {x = 0, y = 0}, {w = ui.window_size.w, h = 140})
+ ui:rectUpdate(vars.narration.rect.id, vars.narration.rect.position, vars.narration.rect.size)
+ -- ui:rectUpdate(ui.doWhat.id, ui.doWhat.position, ui.doWhat.size)
+ --
+ -- local format = string.format("Do what with %s?", params.my_clonemon[ui.clonemon_selected].name)
+
+ ui:textChange("narration", "do_what", "Move to where?" , fg_color2, bg_color)
+ ui:updateText("narration", "do_what", {x = 6, y = 146})
+
+ if my_clonemon then
+ for i, clonemon in pairs(my_clonemon) do
+ local name_pos = {
+ x = vars.notSelected_rects[i].position.x + 4,
+ y = vars.notSelected_rects[i].position.y + 4,
+ }
+ ui:updateText2(vars.clonemon[i].ids, "name", name_pos)
+ end
+ end
+ for i = 1, 6 do
+ if vars.clonemon_selected ~= i and vars.clonemon_switch ~= i then
+ ui:rectUpdate(vars.notSelected_rects[i].id, vars.notSelected_rects[i].position, {w = 116, h = 44})
+ end
+ end
+ if vars.clonemon_selected ~= 7 then
+ ui:rectUpdate(vars.notSelected_rects[7].id, vars.notSelected_rects[7].position, {w = 116, h = 15})
+ end
+end
+
+return ui
--- /dev/null
+local assign = require("extensions.metatables.ui")
+local vars <const> = {}
+local ui, ui_mt = assign("partybox", {vars = vars})
+local fg_color = {r = 255, g = 255, b = 255, a = 255};
+local info_fg_color = {r = 0, g = 0, b = 0, a = 255};
+local bg_color = {r = 0, g = 0, b = 0, a = 0};
+local header_fg_color = {r = 255, g = 255, b = 255, a = 255};
+local header_bg_color = {r = 0, g = 0, b = 200, a = 255};
+
+function ui:init(spritesheet, window_size, options)
+ ui_mt:_init(spritesheet, window_size, "NotoSansMono-Regular.ttf", 8, options, function()
+ end)
+end
+
+function ui:startCallback()
+ vars.selection_rect = ui:createRect({r = 102, g = 153, b = 255, a = 50}, true, 2)
+ vars.box_rect = ui:createRect({r = 240, g = 240, b = 240, a = 255}, true, 0)
+ vars.info_rect = ui:createRect({r = 240, g = 240, b = 240, a = 255}, true, 0)
+ vars.selected = 1
+ vars.box_number = 1
+ ui:addText("box", "number", "number", 3, fg_color, bg_color)
+ ui:addBackgroundImage("gradient", "gradient.png")
+ ui:setBackgroundImage("gradient")
+
+ vars.clonemon = {}
+
+ local i = 1
+ for id,tab in pairs(World.clonemon) do
+ for k, v in pairs(tab) do
+ if k == "type_id" then
+ local type = World.clonemon_types[v]
+ ui:addText(tab.name, "type header", "type", 3, header_fg_color, header_bg_color)
+ ui:addText(tab.name, "type", type.name, 3, info_fg_color, bg_color)
+
+ ui:addText(tab.name, "name header", "name", 3, header_fg_color, header_bg_color)
+ ui:addText(tab.name, "name", tab.name, 3, info_fg_color, bg_color)
+
+ ui:addText(tab.name, "level header", "level", 3, header_fg_color, header_bg_color)
+ ui:addText(tab.name, "level", math.floor(tab.level), 3, info_fg_color, bg_color)
+ vars.clonemon[tab.name] = tab
+ vars.clonemon[tab.name].type = type
+ i = i + 1
+ end
+ end
+ end
+
+ -- local clonemon_type = World.clonemon_types[World.clonemon.type_id]
+ -- print(clonemon_type)
+end
+
+function ui:update()
+ ui:updateBackground()
+ local box_pos = {x = 67, y = 27}
+ local box_padding = {
+ right = 8,
+ bottom = box_pos.y,
+ top = 26,
+ left = box_pos.x,
+ }
+ local box_size = {w = 170, h = 130}
+ local select_box_size = {w = (box_size.w - 1) / 5 + 1, h = (box_size.h - 1) / 5 + 1}
+ local x = (vars.selected - 1) % 5
+ local y = math.floor((vars.selected - 1) / 5)
+
+ local select_rect = { x = box_pos.x + (select_box_size.w - 1) * x ,
+ y = box_pos.y + (select_box_size.h - 1) * y }
+
+ ui:rectUpdate(vars.selection_rect, select_rect, select_box_size)
+ ui:rectUpdate(vars.box_rect, box_pos, box_size)
+ ui:rectUpdate(vars.info_rect, {x = 3, y = 3}, {w = 61, h = 154})
+ ui:textChange("box", "number", string.format("box:%d", vars.box_number), fg_color, bg_color)
+ for k,v in pairs(vars.clonemon) do
+ if v.box_number == vars.box_number and v.box_position == vars.selected then
+ ui:updateText(v.name, "type header", {x = 5, y = 6})
+ ui:updateText(v.name, "type", {x = 5, y = 6 + ((ui.font_size + 3) * 1)})
+
+ ui:updateText(v.name, "name header", {x = 5, y = 6 + ((ui.font_size + 3) * 3)})
+ ui:updateText(v.name, "name", {x = 5, y = 6 + ((ui.font_size + 3) * 4)})
+
+ ui:updateText(v.name, "level header", {x = 5, y = 6 + ((ui.font_size + 3) * 6)})
+ ui:updateText(v.name, "level", {x = 5, y = 6 + ((ui.font_size + 3) * 7)})
+ end
+ end
+
+ local size = ui:getTextSize("box", "number")
+ local text_pos = {}
+ text_pos.x = box_padding.left + (box_size.w / 2) - (size.w / 2)
+ text_pos.y = 5
+
+ ui:updateText("box", "number", text_pos)
+end
+
+return ui
--- /dev/null
+local assign = require("extensions.metatables.ui")
+local vars <const> = {}
+local ui, ui_mt = assign("settings", {vars = vars})
+
+function ui:init(window_size, options)
+ ui_mt:_init(nil, window_size, "NotoSansMono-Regular.ttf", 6, options, function()
+ ui.start_time = nyq.getTicks()
+ end)
+end
+
+function ui:setOptions()
+ local bg_color = {r = 0, g = 0, b = 0, a = 0}
+ local fg_color = {r = 128, g = 128, b = 128, a = 0}
+ local fg_color_selected = {r = 255, g = 255, b = 255, a = 0}
+
+ vars.selected = 1
+ vars.subselected = 1
+ vars.select_options = {}
+ vars.subselection_max = 0
+ vars.temp_settings = Copy.shallow_copy({
+ controller = Ex.Config.db.controller,
+ fullscreen = Ex.Config.db.fullscreen,
+ resolution_scale = Ex.Config.db.resolution_scale,
+ speed = Speed_options[Ex.Config.db.speed],
+ })
+
+ ui:setControllerOptions()
+ vars.select_options = {
+ [1] = {
+ name = "resolution_scale",
+ value = Ex.Config.db.resolution_scale,
+ options = {
+ [1] = 3,
+ [2] = 4,
+ [3] = 5,
+ [4] = 6,
+ }
+ },
+ [2] = {
+ name = "speed",
+ value = "x" .. tostring(Speed_options[Ex.Config.db.speed]),
+ options = Speed_options
+ },
+ [3] = {
+ name = "controller",
+ value = Ex.Config.db.controller,
+ options = vars.controller_options
+ },
+ [4] = {
+ name = "fullscreen",
+ value = Ex.Config.db.fullscreen and "true" or "false",
+ options = {
+ [1] = true,
+ [2] = false,
+ }
+ },
+ [5] = {
+ name = "map controller"
+ },
+ [6] = {
+ name = "map keyboard"
+ },
+ [7] = {
+ name = "reset"
+ },
+ [8] = {
+ name = "apply"
+ },
+ [9] = {
+ name = "go back"
+ },
+ }
+
+ vars.selection_max = #vars.select_options
+ vars.rect_id = ui:createRect({r = 26, g = 26, b = 26, a = 255}, true, 2)
+ vars.selected_submenu = false
+ ui:addText("warnings", "restart", "restart required", 1, {r = 255, g = 0, b = 0, a = 150}, bg_color);
+ ui.restart_required = false
+
+ for k, v in pairs(vars.select_options) do
+ if v.value then
+ ui:addText("menu", v.name, v.name .. ": ".. v.value, 1, fg_color, bg_color)
+ ui:addText("menu", v.name .. " selected", v.name .. ": " .. v.value , 1, fg_color_selected, bg_color)
+ else
+ ui:addText("menu", v.name, v.name, 1, fg_color, bg_color)
+ ui:addText("menu", v.name .. " selected", v.name, 1, fg_color_selected, bg_color)
+ end
+ if v.options then
+ for k2, v2 in pairs(v.options) do
+ ui:addText("submenu", v.name .. k2, tostring(v2), 3, fg_color, bg_color)
+ ui:addText("submenu", v.name .. k2 .. " selected", tostring(v2), 3, fg_color_selected, bg_color)
+ end
+ end
+ end
+end
+
+function ui:setControllerOptions()
+ local gamepads = nyq.getGamepads()
+ if gamepads then
+ vars.controller_options = gamepads
+ vars.controller_options[#gamepads + 1] = "none"
+ else
+ vars.controller_options = {}
+ vars.controller_options[1] = "none"
+ end
+end
+
+function ui:startCallback(params)
+ ui:setOptions()
+end
+
+function ui:update()
+ ui:setControllerOptions()
+ for k, v in pairs(vars.select_options) do
+
+ local y =
+ (unscaled_window_size.h / 2) -
+ ( ((ui.font_size + 1) * #vars.select_options) / 2)
+ + ((ui.font_size + 1) * k)
+
+ local f = v.name
+ if vars.selected == k then
+ f = v.name .. " selected"
+ end
+
+ local size = ui:getTextSize("menu", f)
+ local x = (unscaled_window_size.w / 2) - (size.w / 2)
+ ui:updateText("menu", f , {x = "center", y = y})
+
+ if vars.selected_submenu and vars.selected == k and v.value then
+ local h = ((ui.font_size + 1) * #v.options) + 2
+ ui:rectUpdate(vars.rect_id, {x = x, y = y + ui.font_size + 1}, {w = size.w, h = h})
+
+ if v.options then
+ for k2, _ in pairs(v.options) do
+ if k2 == vars.subselected then
+ vars.subselection_max = #v.options
+ ui:updateText("submenu", v.name .. k2 .. " selected", {x = "center", y = y + ((ui.font_size + 1) * k2 )})
+ else
+ ui:updateText("submenu", v.name .. k2, {x = "center", y = y + ((ui.font_size + 1) * k2 )})
+ end
+ end
+ end
+ end
+
+ if k == #vars.select_options and vars.restart_required then
+ size = ui:getTextSize("warnings", "restart")
+ ui:updateText("warnings", "restart", {x = "center", y = y + ui.font_size + 5})
+ end
+
+ end
+
+ ui:notifyUpdate()
+end
+
+return ui
--- /dev/null
+local spritesheet <const> = "logo.png"
+local assign = require("extensions.metatables.ui")
+
+local vars <const> = {
+ images = {
+ clonemon = {
+ position = {x = 0, y = 0},
+ },
+ },
+ company = {
+ name = nil,
+ },
+ songPlayed = false,
+ selection = {
+ continue = nil,
+ },
+ count = 0,
+ angle = 0,
+ rotate = 370,
+ rotate_sign = 1,
+ start_time = nyq.getTicks(),
+}
+
+local ui, ui_mt = assign("start", vars)
+
+
+function ui:init(window_size, options)
+ ui_mt:_init(spritesheet, window_size, "NotoSansMono-Regular.ttf", 12, options, function()
+ local pos = {x = 0, y = 0}
+ end)
+end
+
+function vars:companyName()
+ nyq.clear({r = 0, g = 0, b = 0, a = 255})
+ ui:updateText("company", "name", {x = 60, y = 140})
+end
+
+function ui:startCallback()
+ nyq.hasFrameCap(true)
+ -- ui.images.clonemon.id = nyq.images.create("clonemon.png", 0)
+ ui.images.clonemon.id = ui:imageCreate("clonemon.png", 0)
+ local fg_color = {r = 255, g = 255, b = 204, a = 255}
+ local fg_color2 = {r = 0, g = 0, b = 0, a = 255}
+ local bg_color = {r = 0, g = 0, b = 0, a = 0}
+ local str = "made by NyqSoft"
+ ui:addText("company", "name", str, 5, {r = 255, g = 255, b =255, a = 255}, bg_color)
+ ui:addText("selection", "continue", "press 'select' to continue", 5, fg_color, bg_color)
+ ui:addText("selection", "continue2", "press 'select' to continue", 5, fg_color2, bg_color)
+ Ex.Audio.init({
+ intro = {file = "intro.wav", loop = -1},
+ })
+ if ui.songPlayed then
+ Ex.Audio.play("intro")
+ end
+end
+
+function ui:songPlayIntro()
+ if not ui.songPlayed then
+ Ex.Audio.stopAll()
+ Ex.Audio.play("intro")
+ end
+ ui.songPlayed = true
+end
+
+function ui:update()
+ if nyq.getTicks() - ui.start_time >= 1500 then
+ ui:songPlayIntro()
+ nyq.clear({r = 255, g = 128, b = 128, a = 255})
+ ui.angle = 90
+ ui.images.clonemon.position.x = (math.cos(ui.angle ) * 2) + ( 20)
+ ui.images.clonemon.position.y = (math.sin(ui.angle ) * 2) + ( 20)
+
+ ui:imageUpdate(ui.images.clonemon.id, ui.images.clonemon.position, {
+ w = (ui.window_size.w - 50) , h = (ui.window_size.h - 50)
+ })
+
+ Ex.Images.rotate(ui.images.clonemon.id, ui.rotate)
+ ui.rotate = ui.rotate - (nyq.deltaTime * 30) * ui.rotate_sign
+
+ if ((ui.rotate <= 350) or (ui.rotate >= 370)) then
+ ui.rotate_sign = ui.rotate_sign * -1
+ end
+
+ ui:updateText("selection", "continue2", {x = 25 - 1, y = 140 + 1})
+ ui:updateText("selection", "continue", {x = 25, y = 140})
+ return false
+ else
+ nyq.clear({r = 0, g = 0, b = 0, a = 255})
+ ui:updateText("company", "name", {x = 60, y = 140})
+ return true
+ end
+end
+
+return ui
--- /dev/null
+local assign = require("extensions.metatables.ui")
+local vars <const> = {}
+local ui, ui_mt = assign("start_menu", {vars = vars})
+
+function ui:init(window_size, options)
+ ui_mt:_init(nil, window_size, "NotoSansMono-Regular.ttf", 6, options, function()
+ end)
+end
+
+function ui:startCallback(params)
+ local bg_color = {r = 0, g = 0, b = 0, a = 0}
+ local fg_color = {r = 128, g = 128, b = 128, a = 0}
+ local fg_color_selected = {r = 255, g = 255, b = 255, a = 0}
+
+ ui:addText("menu", "play", "play", 5, fg_color, bg_color)
+ ui:addText("menu", "play selected", "play", 5, fg_color_selected, bg_color)
+
+ ui:addText("menu", "settings", "settings", 5, fg_color, bg_color)
+ ui:addText("menu", "settings selected", "settings", 5, fg_color_selected, bg_color)
+
+ ui:addText("menu", "help", "help", 5, fg_color, bg_color)
+
+ ui:addText("menu", "help selected", "help", 5, fg_color_selected, bg_color)
+ vars.selected = 1
+ vars.select_options = {}
+ vars.select_options["play"] = 1
+ vars.select_options["settings"] = 2
+ vars.select_options["help"] = 3
+ vars.selection_max = 3
+end
+
+function ui:update()
+ for v, i in pairs(vars.select_options) do
+ if vars.selected == i then
+ v = v .. " selected"
+ end
+ ui:updateText("menu", v , {x = 22, y = 105 + ((ui.font_size + 1) * i)})
+
+ end
+end
+
+return ui
--- /dev/null
+local player_spritesheet <const> = "nyquist_spritesheet.png"
+local ai <const> = require("modules.ai")
+local player <const> = require("modules.player")
+local vars <const> = {}
+local assign = require("extensions.metatables.ui")
+local ui, ui_mt = assign("world", {vars = vars, ai = ai})
+
+function ui:init(world_name, world_spritesheet,
+ window_size, options)
+ ui_mt:_init(player_spritesheet, window_size, "NotoSansMono-Regular.ttf", 8,
+ options, function()
+ vars.world_spritesheet = world_spritesheet
+ vars.world_name = world_name
+ vars.selection_max = 0
+ vars.start_menu = {}
+ local pos = { x = ui.window_size.w - 55, y = 4 }
+ vars.start_menu.position = pos
+ vars.start_menu.selection = {}
+ vars.start_menu.size = {w = 0, h = 0}
+ end)
+ player:init(ui, "main", ui.spritesheet, ui.scale, .100, ui.window_size)
+ ai:init(world, player, options.scale, window_size)
+ -- ai:setNoClip(false)
+ world:init(4, player, {
+ [1] = {spec = {4, 5, 6}, limit = 6},
+ }, ui.window_size, "spritesheet_outdoor_1.png", "test")
+ world:generate(ui, {
+ hospital = {"house1", "house2"}
+ })
+ -- nyq.world.addObject(0, {
+ -- position = {x = 24, y = 12},
+ -- is_visable = true,
+ -- is_collidable = true,
+ -- hitbox = {x = 0, y = 0, w = 10, h = 10},
+ -- crops = {
+ -- {x = 4, y = 10, w = 14, h = 14}
+ -- }
+ -- })
+ print("world layout:\n")
+ print(world.current_pos)
+ world:print()
+ print()
+end
+
+function ui:startCallback()
+ nyq.hasFrameCap(true)
+ vars.selected = 1
+ vars.selection_rect = ui:createRect({r = 100, g = 0, b = 0, a = 50}, true, 6)
+ vars.text_rect_id = ui:createRect({r = 0, g = 0, b = 0, a = 200}, true, 4)
+ vars.text_pos = 0
+ vars.text_max = 0
+ vars.text_done = false
+ vars.text_end = false
+
+ for i = 1, 3 do
+ local id = string.format("%d", i)
+ ui:addText("text", id, " ", 5,
+ {r = 255, g = 255, b = 255, a = 255},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+ end
+
+ player:start(ui)
+ world:mapStart(ui)
+ ai:start()
+
+ vars.menu_size = #params.menu_items
+ vars.start_menu.id = ui:imageCreate("pause.png", 5)
+
+ local padding = 11
+ local padding_top_and_bottom = 8
+ local fg_color = {r = 0, g = 0, b = 0, a = 0}
+ local bg_color = {r = 255, g = 255, b = 255, a = 0}
+
+ for i, item in ipairs(params.menu_items) do
+ vars.start_menu.selection[i] = {}
+ vars.start_menu.selection[i].position = {x = vars.start_menu.position.x + 8, y = padding_top_and_bottom + padding * (i - 1)}
+ vars.start_menu.selection[i].id = nil
+ ui:addText2(vars.start_menu.selection[i], "id", item.name, 5, fg_color, bg_color)
+ end
+ local text_size = ui:getTextSize2(vars.start_menu.selection[1], "id")
+ vars.start_menu.size = {
+ w = 53, h = ((padding * (vars.menu_size - 1)) +
+ (padding_top_and_bottom)) + text_size.h
+ }
+end
+
+
+function ui:worldUpdate()
+ player:moveUpdate(ui)
+ world:mapUpdate(ui, {
+ scale = ui.scale,
+ })
+end
+
+function ui:pauseUpdate()
+ ui:imageUpdate(vars.start_menu.id,
+ vars.start_menu.position, vars.start_menu.size)
+ local size = ui:getTextSize2(vars.start_menu.selection[vars.selected], "id")
+ local text_pos = vars.start_menu.selection[vars.selected].position
+ ui:rectUpdate(vars.selection_rect,
+ {x = (vars.start_menu.position.x) + (4),
+ y = (text_pos.y)},
+ {w = (vars.start_menu.size.w) - (9),
+ h = size.h})
+ for i, selection in ipairs(vars.start_menu.selection) do
+ ui:updateText2(selection, "id", selection.position)
+ end
+end
+
+function ui:selectUpdate(options)
+ vars.selection_max = ui:optionSelectInit(options)
+ ui:optionSelectUpdate({x = 238, y = 118}, vars.selected)
+end
+
+function ui:textUpdate(text)
+ if vars.text_end then
+ vars.text_end = false
+ return
+ end
+
+ local lines = string.WordWrap(text, 38)
+ vars.text_max = math.ceil(#lines / 3)
+
+ for i = 1, 3 do
+ if not lines[i + (vars.text_pos * 3)] then
+ vars.text_done = true
+ break
+ end
+ local id = string.format("%d", i)
+ local y = 130 + ((i - 1) * (ui.font_size + 1))
+ ui:textChange("text", id, lines[i + (vars.text_pos * 3)],
+ {r = 255, g = 255, b = 255, a = 255},
+ {r = 0, g = 0, b = 0, a = 0}
+ )
+ ui:updateText("text", id, {x = 54, y = y})
+ end
+
+ player:faceUpdate(ui)
+ ui:rectUpdate(vars.text_rect_id,
+ {
+ x = 50,
+ y = 130
+ },
+ {
+ w = 190,
+ h = 30
+ })
+end
+
+
+return ui