0     888]]]}}}UU4e<(0@
@          2Tv2Tv2TvͫgE#               DDDD43334433433343C3433344344333DDDD333343433333C33C333333333333DDD4333#434#333#3C##333#333#333#ffffVUUUVVUUVUUUVUeUVUUUVVUVVUUUffffUUUUVUVUUUUUeUUeUUUUUUUUUUUUfffVUUUEVUVEUUUEUeEEUUUEUUUEUUUEUUUUEOOOEOUUUUOOOOOOUUUU4OO?4O?4OO?4UUUUUUUUUUUU__OOOOO                43334333443343334333433344344333C3C33333333333333C333333333333333###333#333#333##33#332#333#333#VUUUVUUUVVUUVUUUVUUUVUUUVVUVVUUUeUeUUUUUUUUUUUUUUeUUUUUUUUUUUUUUUEEEUUUEUUUEUUUEEUUEUUTEUUUEUUUEOOEOOOEOOOOOOOOOO?4OO?4O?4OO?4OOOOOOOO                43334333443343334333433343434333C33333#34333333333#33333323333333#3#333#333#333##3##333#333#333#VUUUVUUUVVUUVUUUVUUUVUUUVUVUVUUUeUUUUUEUVUUUUUUUUUEUUUUUUTUUUUUUUEUEUUUEUUUEUUUEEUEEUUUEUUUEUUUEOOEOOOEOOOOOOOOOO?4OO?4O?4OO?4OOOOOOOO                43334333433343334C3343334333#"""3333333#23233333333#33333333""""3#3#333#333#333#32##333#333#""""VUUUVUUUVUUUVUUUVeUUVUUUVUUUEDDDUUUUUUUETUTUUUUUUUUEUUUUUUUUDDDDUEUEUUUEUUUEUUUEUTEEUUUEUUUEDDDDOOEOOOEO3333OOOOOOOO3333O?4OO?4O?4OO?3333UUUUEDDDUEDDDDDDOOOOOODDDDDDDD                ffffVUUUVVUUVUUUVUeUVUUUVVUVVUUUffffUUUUVUVUUUUUeUUeUUUUUUUUUUUUfffVUUUEVUVEUUUEUeEEUUUEUUUEUUUEDDDD43334433433343C3433344344333DDDD333343433333C33C333333333333DDD4333#434#333#3C##333#333#333#ffffVvVvwwVvVvVvwVvwVvwffffwwwwwwqqqqqqqfffVgEwwgEqgEgEwgEwgEwgE                VUUUVUUUVVUUVUUUVUUUVUUUVVUVVUUUeUeUUUUUUUUUUUUUUeUUUUUUUUUUUUUUUEEEUUUEUUUEUUUEEUUEUUTEUUUEUUUE43334333443343334333433344344333C3C33333333333333C333333333333333###333#333#333##33#332#333#333#VvwVvwVvwVvwVvVvVvwwVvqqwqwwqqqwwwwwwgEgEwgEwgEgEqgEwwgEgE                VUUUVUUUVVUUVUUUVUUUVUUUVUVUVUUUeUUUUUEUVUUUUUUUUUEUUUUUUTUUUUUUUEUEUUUEUUUEUUUEEUEEUUUEUUUEUUUE43334333443343334333433343434333C33333#34333333333#33333323333333#3#333#333#333##3##333#333#333#VvwwVvqqVvqqVvwwVvqVvqVvwwVvqwwwwqqwwqqwwwwww7s7swwww37s3wwgEwwgEwwgEwwgE7sgE7sgEwwgEqgE                VUUUVUUUVUUUVUUUVeUU&"""2%#""UUUUUUUETUTUUUUUUUUE"-"""""UEUEUUUEUUUEUUUEUTEE"""B2"""C43334333433343334C33$"""2##""3333333#23233333333#"-"""""3#3#333#333#333#32##""""1"""#VvqVvwwVfffVUUUVeUUVUeUVUUUEDDD37s3wwwwffffUUUUUUUEUUTUVUUUDDDDqgEwwgEfffEUUUEUTEETUUEUUUEDDDD                ffffVUUUVVUUVUUUVUeUVUUUVVUVVUUUffffUUUUVUVUUUUUeUUeUUU%UUU"UU%fffVUUUEVU""U""""""ffffVUUU""UU"""U"""ffffUUUUVUVUUUUUeUUeRUUU"UUU/RUUfffVUUUEVUVEUUUEUeEEUUUEUUUEUUUEffffVUUUVVUUVUUUVUeUVUUUVVUVVUUUffffUUUUVUVUUUUUeUUeUUU%UUU"UU%rfffVUUUEVU""U"""""wg"wwgwwwgwwwgffffVUUU""UU"""Uww""www"wwwwwwwwffffUUUUVUVUUUUUeUUeRUUU"UUU'RUUfffVUUUEVUVEUUUEUeEEUUUEUUUEUUUE                VUUUVUUUVVUUVUUUVUUUVUUUVVUVVUUUeU"U%U"U"%%"""eU/RU/"U"U/R/R""UEEEUUUEUUUEUUUEEUUEUUTEUUUEUUUEVUUUVUUUVVUUVUUUVUUUVUUUVVUVVUUUeU"wU%rwU"rwU"ww%rww%rww"www"wwwwwwgwwwgwwwgwwwgwwwgwwwgwwwgwwwgwwwwwwwww"eUw'RU"U"U*R*R""UEEEUUUEUUUEUUUEEUUEUUTEUUUEUUUE                VUUUVUUUVVUUVUU%VUU%VUU%VUV%VUU%""""""/////UEUEUUUEUUUERUUEBUEERUUERUUERUUEVUUUVUUUVVUUVUU%VUU%VUU%VUV%VUU%"www"www"wwwrwwwrwwwrwwwrwwwrwwwwwwgwwwfwwggwwvgwwvgwwvgwwggwwwf"""*****UEUEUUUEUUUERUUEBUEERUUERUUERUUE                VUU%VUU%VUU%VUU%VeUUVUUUVUUUEDDD"""$////"""/BREUERUUERUUERUUEUTEEUUUEUUUEDDDDVUU%VUU%VUU%VUU%VeUUVUUUVUUUEDDDrwwwrwwwrwwwrwww"www"www"www$rwwwwwgwwwgwwwgwwwgwwwgwwwgwwwgwwwg****"""*BREUERUUERUUERUUEUTEEUUUEUUUEDDDD                UUUU̵̵UUUU̻̻UUUU̻̻UUUU̻̻UUUU̻̻UUUULKJLKJLBDDB33B33B33B33B33B33B33DDDD3333333333333333333333333333DD$+33$+33$+33$+33$+33$+33$+33$+""""""23332UUU2UUU2UUU2UUU2UUU""""""""3333UUUUUUUUUUUUUUUUUUUU"""+"""+333#UUU#UUU#UUU#UUU#UUU#DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""                ̵̵̻̻̻̻̻̻̻̻KJLKJLKJB33B33B33B33B33B33B33B333333333333333333333333333333333333$+33$+33$+33$+33$+33$+33$+33$+2UUU2UUU2UUU2UUU2UUU2UUU2UUU2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#UUU#UUU#UUU#UUU#UUU#UUU#UUU#DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""                ̵̵̵̻̻̻̻̻̻̻̻̻̻̻̻LKJLKJLKB33B33B33BDD"""33333333"""333333333333DDDD""""33333333""""33$+33$+33$+DD$+"""+33333333"""+2UUU2UUU2UUU2UUU2UUU3UUU3UUU2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#UUU#UUU#UUU#UUU#UUU#UUU#UUU#DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""                ̵̵UUUUEDDD̻̻UUUUDDDD̻̻UUUUDDDD̻̻DDDDDDDD̻̻DDDDDDDDJLKJLKDDDDDDDD"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""+"""+"""+"""+"""+"""+"""+"""+2UUU2UUU2UUU2UUU2UUU2UUU2UUU2UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU#UUU#UUU#UUU#UUU#UUU#UUU#UUU#                                                                                    www www w w                 ww  ww ww  qw                  wwwpwwwwww                  w  ww www wqw w                wwwwwwwwwww  q                  ww www w                   wwwwwwwwwwww                    ww pww ww ww                ww  ww qww ww                 ww  ww  ww  ww                                  
  
 
 


                                                     y{y{y{y{y~""r~""r~""r~ w  g  v  ggg vvv f f  f  pw  `g  vv gg vv           w  v  g  v  g  f  f  ff  pw w`g vpv g`g vpv g`f f`f fff fw  pv  pg  gvvvvggggfff  ff  aw   v   g               f   ww  vv  gg  vv  gg  ff  ff  ff   ww  vv  gg  vvv ggg ff ff  ff  ww  vv  gg vvv ggg ff  ff  ff ww  vv  gg  vv  gg  ff  ff  ff                                                                                                "ww"wwwwqwwwwww f  f                                                       affffff                     f ff f  ` ``` ``` ```f f  `f  `  `  ``  `  f`f a f   f        `aff  ff    ` ffa`f ff  ff   f              ff  ff                       ffffffff                    ff  ff                         


    
                                                                               DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""wwwggffVgvfVgfVVggfVgfeVgffVVUUUwwwggffVgvfVgfVVggfVgfeVgffVVUUUwwwggffVgvfVgfVVggfVgfeVgffVVUUUUUUUEOOOEOUUUUOOOOOOUUUU4OO?4O?4OO?4UUUUUUUUUUUU__OOOOO                DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""wwwggffVgvfVgfVVggfVgfeVgffVVUUUwwwggffVgvfVgfVVggfVgfeVgffVVUUUwwwggffVgvfVgfVVggfVgfeVgffVVUUUOOEOOOEOOOOOOOOOO?4OO?4O?4OO?4OOOOOOOO                DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""DDD4433#4C3#43##443#432#433##"""wwwggffVgvfVgfVVggfVgfeVgffVVUUUwwwggffVgvfVgfVVggfVgfeVgffVVUUUwwwggffVgvfVgfVVggfVgfeVgffVVUUUOOEOOOEO5333OOOOOOOO3333O?4OO?4O?4OO?3333EDDDDDDDOOOOOOODDDD                шDDD4433#4C3#43##443#432#433##"""DDD4433#4!"!!"!"!"!"!#!#!"!"DDD4433#4C3#43##143#132#133#!"""wwwggffVgvfVgfVVggfVgfeVgffVVUUUwwwggffVgQ"!!"!"!"!"!#!#!"!"wwwggffVgvfVgfVVagfVafeVaffVQUUU                                                                DDD4433#4C3#43##443#432#433##"""!"!"!"!"!"!"!"!"!#!#!"!"!*"ADD4133#1C3#13##143#132#133#!"""wwwggffVgvfVgfVVggfVgfeVgffVVUUU!"!"!"!"!"!"!"!"!#!#!"!"!*"qwwgaffVavfVafVVagfVafeVaffVQUUU                                                                DDD4433#4C3#43##443#432#433##"""!"""!"#"!#"#!"""!!"!4!#"""ADD4133#1C3#13##143#432#433##"""wwwggffVgvfVgfVVggfVgfeVgffVVUUU!"""!"#"!#"#!"""!!"!gQVUUUqwwgaffVavfVafVVagfVgfeVgffVVUUU                                                                   
              fddFDDDKFKKDKFDDfdd"""233233""""+www/"www////333󣪪󣠠
󣠠󣪪333""""""                                                                                

  

     

  

                                                              wwww                                                                UUUUeffVeffVeffVeffVeffEefVDUUEDTUUETffETffETffEDUUDDDDDDDDDDDDDUUUUeffVeffVeffVeffVTffVDefVDTUU""""233323332#""2#2#2#2#""""33333333""""""""333#333#""2#2#2#2#2#                      
   ""  """"""" " w pwppw wwpwwwp www                                                   DDDDUUDDefEefEefEefEDUUDDDDDDIIxIDDDDDDDDUUITfVITfVITfVDTfVDDUUDDDD2#2#2#2#2#2#2#2#2#2#2#2#2#2#2#2#                wwww  wwp  wwwpwww  ww  wwwwwwwpw                 "" /ww"p ww"                                                   UUEDefVDeffEeffVeffVeffVeffVUUUUDIDDDDDDDDDDUUDTffETffETffETUUEDTUUDefVTffVeffVeffVeffVeffVUUUU2#2#2#2#2#""23332333""""""""33333333""""2#2#2#2#""2#333#333#""""                """""""333333        333333                        UUUUeffVeffVeffVeffVeffEefVDUUEDTUUETffETffETffEDUUDDDDDDDDDDDUUUUeffVeffVeffVeffVTffVDefVDTUU""""233324442333BCCC23332444""""""""333344443333CCCC33334444""""""""333#444$333#CCC#333#444$""""                """"{p"""b`3333""""            33 ""         3333""""            33 ""                         DDDDUUDDefEefEefEefEUUDDDDDDJJDDDDDDUUJTfVJTfVJTfVJTfVDDUUDDDD                113111 "3 "3DUfwDUfwwwwwww      ww                  UUEDefVDeffEeffVeffVeffVeffVUUUUDDDDDDDDDDDUUDTffETffETffETUUEDTUUDefVTffVeffVeffVeffVeffVUUUU""""23332333""""""""C4C˼4""""""""333#333#""""                               $$$$$$$(((((((



BBBBBBBBBBBBBB	B	B	B	B	B	B	BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB!B!B!B!B!B!B!B%B%B%B%B%B%B%B)B)B)B)B)B)B)BSSSSBCBBBBBCBBBBBCBBBBBCBBBB	AEIMłɂ͂	BBFBJBNBBBFBJBNBBBFBJBNBBBFBJBNBSBSBSBSB B BQSBBBPSBBB	B	SB(B(B)B)SBBBSB B!B!SB$B%B%SB$ JBB	BBABEBIBMBBBBBBBBBBB	BB,B,B,B,A,A,B,B,B,B,B,A,A,B,B-B-B-B-B-!B-%B-)B-QB-UB-YB-]B-aB-eB-iB        т Ղ ق ݁   !%)QUY]aei  /o/o	/	o/o/o/o/o/o  !/!o$$%/%o(()/)o))""    ((((((((   }QbR<t< < &*l.%nl.	| p p qqrrssttuuvvw	w
x
xyyz{{|}}~                                         	
		

      6789:;<
=> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?     @BDEF	GIJKLL L L L M N N O O O O O O O O O O O O O      C D FGHIJJJK	L
L	MO O O O O O O O O O O O O O O O O     0 01122334455667	7
8
899:;;<==>???    00 2 345789:;<==>>???????????????                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    0 0 0 ; < = 0	0	0	;	<	=	? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?     0 0 0 ; < = 0	0	0	;	<	=	000;<=?? ? ? ? ? ? ? ? ? ? ?                                     < : ; < = = > > > > > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               	 
      @& _         
_         _      _      _   _         
_         _      _      _   _         
_         _      _      _   _         
_         _      _      _    @                                                                               
      
                           
      
                                 
                                                      
      
                           
      
                                 
                                 	         	                      0                                                                                                                                                                                                                                    ~                           _~~   ~^^_               _~~~~~~~_^_~                           ?___?___?___?___?___?___?___?___?___?___?___?___?___?___?___?___~                           _~   ~   ~^^_                  ~~~~~~_      __                        ?___?___?___?___?___?___?___?___?___?___?___?___?___         00                         ~~~~^_~~~~~~~~~                  >^^_^^^_>>>?^^^_^^^_^^^_>>>?^^^_^^^_>>>?^^^_^^^_^^^_>>>??___?___^_^_^_^_^_^_^_^_^_^_^_^_^____^_^_^_^_^^^_^_^_^__^_^_^___                                                                                 _~~                           ~~~~^^_                  ~~~~~~~_^_~                        _~                           _~   ~   ~~                  ~~~~                                                            ~                              ~   ~   ^^_                                          ~~~_   __~~~~__~~~~~~~?___?___?___?   __      __   ??   ??      __      __   ??   ??      __      __   ??   ??      __      __   ?~~~^^__~~~~~~~^^__~~~~~~~^^__~~~~~~~^^?   ??      __         ?___?___?___?___?___?___?___?___?___?___?___?___?___?^_~~~~~~~~~~                                                                                                                                          ___?___??___?___                                                                                                                                                >>>>>>>>>>>>>>>>^^^^^^^^>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>	>	>	>	>	>	>	>	>~~      ~~   ~~   ~~   ~~   ~~   ~~   ~~      ~~   ~~      ~~   ~~   ~~   ^^_   ~~   ^^_   ^^_   ^^_   ^^_   ^^_   ^^_   ^^_   ~~   ^^_   ^^_   ~~   ^^_   ^^_   ^^_                                                                                                                                                                                                                                                                                                                                                                                                   	\	\	\	\	\	\	\	\||||\\\\\\\\\\\\\\\\\\\\	\	\	\	\	\	\	\	\||||\\\\\\\\\\\\\\\\\\\\	|	|	|	|	|	|	|	|||||||||||||||||||||	|	|	|	|	|	|	|	|||||||||||||||||||||	~~~	~~~	~~~~~~~	~~~	~~~	~~~~~~~	~~~	~~~	~~~~~~~	~~~	~~~	~~~~~~~		                  @0                                                                                                                                                                      	~	                                                                                                                                                                                          	                  	      	                        	                  	      	                        	~      ~   ~   ~   ~   	~   ~   	~      ~   ~      ~   ~   ~   	~      ~   ~   ~   ~   	~   ~   	~      ~   ~      ~   ~   ~   													]}]]]]	]]	]}]]}]]]	]}]]]]	]]	]}]]}]]]	]}]]]]	]]	]}]]}]]]	]}]]]]	]]	]}]]}]]]													]                                                                                                                                                                                             	}                                                                                                                                                                                             			   			                                                                                                                                                            	~	~	   	~	~	   	~	~	~	~	                                                                                                                                                         	}	}	|   	}	}	|   }}}}|                                  0                                                                                                                      	]	]	\   	]	]	\   ]]]]\                                                                                                                                                         	\	\	\	\	\	\	\	\||||\\\\\\\\\\\\\\\\\\\\	\	\	\	\	\	\	\	\||||\\\\\\\\\\\\\\\\\\\\I}	|}|}|}|}|	}	|}|	}	|}|}|}|}|}|	}	|}|}|}|}|	}	|}|	}	|}|}|}|}|}|	<	<	<	<	<	<	<	<\\\\<<<<<<<<<<<<<<<<<<<<	<	<	<	<	<	<	<	<\\\\<<<<<<<<<<<<<<<<<<<<I]	\}|]\]\]\]\	]	\]\	]	\}|]\]\}|]\]\]\	]	\}|]\]\]\]\	]	\]\	]	\}|]\]\}|]\]\]\	~I~~~~	~	~	~	~~~~~	~	~~~~	~	~	~	~~~~~	^I_~^_^_^_^_	^	_^_	^	_~^_^_~^_^_^_	^	_~^_^_^_^_	^	_^_	^	_~^_^_~^_^_^_	[	[	[	[	[	[	[	[{{{{[[[[[[[[[[[[[[[[[[[[	[	[	[	[	[	[	[	[{{{{[[[[[[[[[[[[[[[[[[[x[											                                              pY pY vY vY                                    
 uuu@uuu#u[ih                       в ۲  @                                                                                                                                                                                          H    P  T                       ? fffffffffffffffffefffffffVffffffffefffffffVoVUVeUVeEfUUUVeUVdVUUeUVeEfUUUVeUVdVUUeUVeEoUUUUUUUUVUUUUUUUeUUUUUUUEVUUUUUUUdUUUUUUUEVeUVUVeUTUVeUeUFEUeUVUVeTVUVUUeUEdUUeUUUVD_UUUUUUUeUUUUUUUEVUUUUUUUTUUUUUUUeUUUUUUUEoUUUUUUUEUUUUUUUUVUUUUUUUdUUUUUUUeUUUUUUUEUUUVUUUDVUUVeUEUTUUUUUUEdUUeUVUDEUUUUVUUDVUUUUUUUTUUUUUUUdUUUUUUUeUUUUUUUEUUUUUUUEoUUUUUUUdUUUUUUUeUUUUUUUEUUUUUUUEUUUUUUUEoUUUeUEUEUUUeUEUEUUUeUEUEUUUeUEUEVUUeUEUEVUUUUUEEVUUUUUEEVUUUUUEEVUUUUUEEVUUUUUEE_UUUUUUUTUUUUUUUVUUUUUUUVUUUUUUEVUUUUUUEoUUeUUUUdUUeUUEUTUUUUUEUVUUVUUEUVUUVUUUEUUUUTUUeUUUUTUUdUUUUUUUTUUUEUUUVUUUUUUEVUUUUUUEVUUUUUUeUUUUUUUdUUUUUUUVUUUUUUEoUUUEUTTVUUUUEUDUUUUTUEeUUUUUTUTUUUEUUDUVUTUUUdeUEUUUUVUUUUUUeUVUUUUUTeUEUUUEVUUUUUUeUUUUUUUTUUUUUUEUUUUUUUTUUUUUUE_UUUUTUEUUUUEUUTUUUUTUEVUUUEUUdUUUUTUEoUUTUUUUVUEUUUUeUUTUUUUVUEUUUUdUUTUUUEVUUUEEETUUUUTUEeUUUUUUVVUUUEEeeUUUTTD_UUUUUUeUUUUUUEVUUUUUUTUUUUUUeUUUUUUE       PDDDDDDDDDDDDDDEDDDDDDDDDDDDDTDDDDDDD                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         *@          2TvͫgE#2Tv2Tv            !                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    D  DD DDDDDDD   D  DD DDDDDDDDDDDDDDDDDDDDDDDD   DD  DDD DDDDDDDDDDDDDDDDDDDD                D   DD  DDD DDDD                                                                                                                                                                                                                                                                                                                                                   D   D           D  DD DDDDDDDDDDDDDDDDDDD DDDDDDDDDDDDDDDDDDDDDD DD  D       DDD DD  D                        DDD  DD   D                    DDDDDDDDDDDDDDDD DDD  DD   D    D   DD  DDD DDDDDDDDDDDDDDDDDDDD                D   DD  DDD DDDD                                                                                                                                                                                                                                                                3   33  333 33333333333333333333  D             3   33  333 3333                                                                                                                                 DDD  DD   D                    DDD3DD33D33333333333333333333333                                                                                                                                                                                                                                                                33333333333333333333333333333333333333333333333333333333333333333   33  333 33333333333333333333                3   33  333 3333                                                                                                33333333333333333333333333333333                                                                                                                                                                                                                                                                33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333                                                                                                33333333333333333333333333333333                                                                                                                                                                                                                                                                33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333                                                                                                33333333333333333333333333333333                                                                                                                                                                                                                                                                33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333                                                                                       3  33 33333333333333333333333333333333333                                                                                                                                                                                                                                                                3333 333  33   3                33333333333333333333 333  33   33333333333333333333333333333333333333333333333333333333333333333                       3  33 333       3  33 333333333333333333333333333333333333333333 33  3   3333333 33  3                                                                                                                                                                                                                                                                                                                                                   3333 333  33   3                33333333333333333333 333  33   3 333 333 333 333 333 33  3      3333333 33  3$  b f jbfjbfj b f j$b$f$j(b(f(j B F J$B$F$J(B(F(J " & *"&*"&*"&*"&*"&*"&*"&* " & *$"$&$*("(&(*   
     $$$
$$$$$(((
((((( ! % )        т Ղ ق ݂    e i a /// o  ooooooo /$/(////// #$#(#,!A,%A,)A,AB,EB,IB,MB,QB,UB,YB,]B,aB,eB,iB,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,B,A,A,	A!%) ! % )#B#B#B#B#BcBBBcBBBcBBBcBBBcBBB #A#A#A A$A(ACBBBBCBBBBCBBBBCBBBB CB B$CB$B(CB(B cBcBcB o $o$(o(     B B B      M Q U Y ]        	 B B B B B B B B B B B$B$B$B$B$B$B$B$B$B$B$B(B(B(B(B(B(B(B(B(B(B(B"B&B*B"B&B*B	"B	&B	*B"B&B*B"B&B*B"B&B*B"B&B*B"B&B*B $(BFJBFJBFJBFJNNNOς[[[MBBBBAEIMłɂ͂	QUNARAVANARAVANARAVABBBBBBBB	B	B	B	BBBBBBBBBBBBBBBBBBBB
BBB
B	B	B	
B	B         ł ɂ ͂  B BBB B AAAAABAFAJABAFAJABAFAJABAFAJQBUBBBAAAAсՁہہہ B B B!B!B!	BSSSNR!N!R%N%R!J%JAAA!A!A!A%A%A%AKA!KB%KAW!W%W)IA)MA)QAIMQ   QQzn _*)  0 1 3 4 5 6 9 : ; < = = > > > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? C      ! ! " " # # $ $ % % & & ' ' ( ( ) ) * * + + , , - - . . / C/ A                                             A                                             A                                             A                                             A                                             A                                             A                                             A                                                   `         `                                                                                 `         `                     `                                                               `         `                                                                                 `                           `                                 .3  0                                               D   %   -- title:  Portal 3D lvl editor
-- author: HanamileH, soxfox42
-- desc:   version 1.0 (powered by UniTIC v 1.3)
-- script: lua
-- saveid: portal3d_unitic_lvl_editor

local save_reminder = true

local map_bank = pmem(0)
local map_bank_state = {false,true,false,false,false,false,false,false} -- false x8
--[[
Everything related to portals or other less important
parts has been cut out in order to speed up the code
]]

--[[
license:

Copyright 2022 HanamileH
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall
be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]

trace("Current map bank: "..map_bank,3)
trace([[To export the map, enter: export map [filename] bank=<bank id> ]],5)
trace([[To import the map, enter: import map [filename].map bank=<bank id> ]],5)
--- Compression routines - placed high as they may be used to compress various pieces of data in the source
local function bitwriter()
	return {
		cur = 0,
		bits = 0,
		output = {},

		write = function(self, val, bits)
			self.cur = self.cur | (val << self.bits)
			self.bits = self.bits + bits
			self:flush()
		end,
		flush = function(self)
			while self.bits >= 8 do
				self.output[#self.output + 1] = string.char(self.cur & 0xFF)
				self.bits = self.bits - 8
				self.cur = self.cur >> 8
			end
		end,
		finish = function(self)
			self.output[#self.output + 1] = string.char(self.cur)
			self.bits = 0
			self.cur = 0
			return table.concat(self.output)
		end,
	}
end

local function bitreader(data)
	return {
		data = data,
		pos = 1,
		bits = 0,

		read = function(self, bits)
			local value = 0
			local cur = 0

			if self.bits > 0 then
				if bits >= (8 - self.bits) then
					value = self:byte() >> self.bits
					cur = 8 - self.bits
					self.bits = 0
					self.pos = self.pos + 1
				else
					value = (self:byte() >> self.bits) & ((1 << bits) - 1)
					self.bits = self.bits + bits
					return value
				end
			end

			while (cur + 8) <= bits do
				value = value | (self:byte() << cur)
				cur = cur + 8
				self.pos = self.pos + 1
			end

			if cur < bits then
				value = value | (self:byte() & ((1 << bits - cur) - 1)) << cur
				self.bits = bits - cur
			end

			return value
		end,
		byte = function(self)
			return string.byte(self.data, self.pos, self.pos)
		end,
	}
end

local function compress(str)
	local writer = bitwriter()

	local codes = {}
	for i = 1, 256 do
		codes[string.char(i - 1)] = i
	end
	local count = 256
	local bits = 9
	local inc = 512

	local start = 1

	while start <= #str do
		for i = start, #str do
			local cur = str:sub(start, i)
			if i == #str then
				writer:write(codes[cur], bits)
				start = i + 1
				break
			end

			local nxt = str:sub(start, i + 1)
			if not codes[nxt] then
				writer:write(codes[cur], bits)
				count = count + 1
				codes[nxt] = count
				start = i + 1
				break
			end
		end

		if count == inc then
			inc = inc * 2
			bits = bits + 1
		end
	end

	writer:write(0, bits)
	return writer:finish()
end

local function decompress(str)
	local reader = bitreader(str)

	local codes = {}
	for i = 1, 256 do
		codes[i] = string.char(i - 1)
	end
	local bits = 9
	local inc = 512

	local result = {}
	local prev

	while true do
		local code = reader:read(bits)
		if code == 0 then
			return table.concat(result)
		end

		if codes[code] then
			result[#result + 1] = codes[code]
			if prev then
				codes[#codes + 1] = prev .. codes[code]:sub(1, 1)
			end
			prev = codes[code]
		else
			local new = prev .. prev:sub(1, 1)
			result[#result + 1] = new
			codes[#codes + 1] = new
			prev = new
		end

		if #codes == inc - 1 then
			inc = inc * 2
			bits = bits + 1
		end
	end
end

local F, R, min, max, abs = math.floor, math.random, math.min, math.max, math.abs
local pi2 = math.pi / 2

--camera
local cam = { x = 0, y = 0, z = 0, tx = 0, ty = 0 }
--player
local plr = {
	speed = 4,
	--coordinates
	x = 528,
	y = 192,
	z = 576,
	--last coordinates
	lx = 528,
	ly = 192,
	lz = 576,
	--velocity
	vx = 0,
	vy = 0,
	vz = 0,
	--rotation
	tx = 0.7,
	ty = pi2,
	--cheats
	noclip = true,
	--stuff
	on_ground=true,
	cd=0,
	dt=1
}

--engine settings:
local unitic = {
	version = 1.3, --engine version
	--drawing
	fov = 80, --lens distance to camera
	--system tables (dont touch)
	poly = {},
	obj  = {}, --objects
	p    = {} --particles
}

-- Please note than some objects do not have collisions. (coll={})
local model={
	{--cube (1)
	v={{ 23.9, 23.9, 23.9},{ 23.9,-23.9, 23.9},{ 23.9, 23.9,-23.9},{ 23.9,-23.9,-23.9},{-23.9, 23.9, 23.9},{-23.9,-23.9, 23.9},{-23.9, 23.9,-23.9},{-23.9,-23.9,-23.9},},
	f={
		 {5,3,1,uv={{96,256},{72,232},{72,256},-1},f=2},
		 {3,8,4,uv={{96,232},{72,256},{96,256},-1},f=2},
		 {7,6,8,uv={{96,232},{72,256},{96,256},-1},f=2},
		 {2,8,6,uv={{96,256},{72,232},{72,256},-1},f=2},
		 {1,4,2,uv={{96,232},{72,256},{96,256},-1},f=2},
		 {5,2,6,uv={{96,232},{72,256},{96,256},-1},f=2},
		 {5,7,3,uv={{96,256},{96,232},{72,232},-1},f=2},
		 {3,7,8,uv={{96,232},{72,232},{72,256},-1},f=2},
		 {7,5,6,uv={{96,232},{72,232},{72,256},-1},f=2},
		 {2,4,8,uv={{96,256},{96,232},{72,232},-1},f=2},
		 {1,3,4,uv={{96,232},{72,232},{72,256},-1},f=2},
		 {5,1,2,uv={{96,232},{72,232},{72,256},-1},f=2},
	},
	coll={{-24,-24,-24,24,24,24}} --collision cube {XYZ, XYZ}
	},
	{--cube companion (2)
	v={{ 23.9, 23.9, 23.9},{ 23.9,-23.9, 23.9},{ 23.9, 23.9,-23.9},{ 23.9,-23.9,-23.9},{-23.9, 23.9, 23.9},{-23.9,-23.9, 23.9},{-23.9, 23.9,-23.9},{-23.9,-23.9,-23.9},},
	f={
		 {5,3,1,uv={{96,256-24},{72,232-24},{72,256-24},-1},f=2},
		 {3,8,4,uv={{96,232-24},{72,256-24},{96,256-24},-1},f=2},
		 {7,6,8,uv={{96,232-24},{72,256-24},{96,256-24},-1},f=2},
		 {2,8,6,uv={{96,256-24},{72,232-24},{72,256-24},-1},f=2},
		 {1,4,2,uv={{96,232-24},{72,256-24},{96,256-24},-1},f=2},
		 {5,2,6,uv={{96,232-24},{72,256-24},{96,256-24},-1},f=2},
		 {5,7,3,uv={{96,256-24},{96,232-24},{72,232-24},-1},f=2},
		 {3,7,8,uv={{96,232-24},{72,232-24},{72,256-24},-1},f=2},
		 {7,5,6,uv={{96,232-24},{72,232-24},{72,256-24},-1},f=2},
		 {2,4,8,uv={{96,256-24},{96,232-24},{72,232-24},-1},f=2},
		 {1,3,4,uv={{96,232-24},{72,232-24},{72,256-24},-1},f=2},
		 {5,1,2,uv={{96,232-24},{72,232-24},{72,256-24},-1},f=2},
	},
	coll={{-24,-24,-24,24,24,24}}
	},
	{ --cube dispenser (3)
		v={
			{ 32, 31, 32},
			{ 32,-32, 32},
			{ 32, 31,-32},
			{ 32,-32,-32},
			{-32, 31, 32},
			{-32,-32, 32},
			{-32, 31,-32},
			{-32,-32,-32},
		},
		f={
			{5,3,1,uv={{120,232},{96, 208},{96 ,232},-1},f=3},
			{3,8,4,uv={{120,232},{96, 256},{120,256},-1},f=3},
			{7,6,8,uv={{120,232},{96, 256},{120,256},-1},f=3},
			{2,8,6,uv={{120,232},{96, 208},{96 ,232},-1},f=3},
			{1,4,2,uv={{120,232},{96, 256},{120,256},-1},f=3},
			{5,2,6,uv={{120,232},{96, 256},{120,256},-1},f=3},
			{5,7,3,uv={{120,232},{120,208},{96 ,208},-1},f=3},
			{3,7,8,uv={{120,232},{96, 232},{96 ,256},-1},f=3},
			{7,5,6,uv={{120,232},{96, 232},{96 ,256},-1},f=3},
			{2,4,8,uv={{120,232},{120,208},{96 ,208},-1},f=3},
			{1,3,4,uv={{120,232},{96, 232},{96 ,256},-1},f=3},
			{5,1,2,uv={{120,232},{96, 232},{96 ,256},-1},f=3}
		},
		coll={{-24,-24,-24,24,24,24}}
	},
	{--light bridge (-X) (4)
		v={{-48,4, 48},{ 48,4, 48},{-48,4,-48},{ 48,4,-48}},
		f={{2,1,4,uv={{0,232},{16,232},{0,248}},f=3},{1,4,3,uv={{16,232},{0,248},{16,248}},f=3}},
		coll={{-48,0,-48,48,0,48}}
	},
	{ --light bridge (+X) (5)
		v={{-48,4,-48},{ 48,4,-48},{-48,4, 48},{ 48,4, 48}},
		f={{1,2,3,uv={{0,232},{16,232},{0,248}},f=3},{2,3,4,uv={{16,232},{0,248},{16,248}},f=3}},
		coll={{-48,0,-48,48,0,48}}
	},
	{--light bridge (-Z) (6)
		v={{-48,4,-48},{-48,4, 48},{ 48,4,-48},{ 48,4, 48}},
		f={{2,1,4,uv={{0,232},{16,232},{0,248}},f=3},{1,4,3,uv={{16,232},{0,248},{16,248}},f=3}},
		coll={{-48,0,-48,48,0,48}}
	},
	{--light bridge (+Z) (7)
		v={{ 48,4, 48},{ 48,4,-48},{-48,4, 48},{-48,4,-48}},
		f={{2,1,4,uv={{0,232},{16,232},{0,248}},f=3},{1,4,3,uv={{16,232},{0,248},{16,248}},f=3}},
		coll={{-48,0,-48,48,0,48}}
	},
	{--button -X (8)
		v={
			{6   ,46  ,6   },
			{6   ,0   ,6   },
			{6   ,46  ,-6  },
			{6   ,0   ,-6  },
			{-6  ,51.2,6   },
			{-6  ,0   ,6   },
			{-6  ,51.2,-6  },
			{-6  ,0   ,-6  },
			{-4.5,51.2,-4.5},
			{-4.5,51.2,4.5 },
			{5.5 ,47.2,-4.5},
			{5.5 ,47.2,4.5 },
		},
		f={
			{5 ,3 ,1 ,uv={{125,136},{120,133},{120,136},-1},f=2},
			{3 ,8 ,4 ,uv={{128,128},{125,132},{128,132},-1},f=2},
			{7 ,6 ,8 ,uv={{128,128},{125,132},{128,132},-1},f=2},
			{1 ,4 ,2 ,uv={{125,132},{128,128},{125,128},-1},f=2},
			{6 ,1 ,2 ,uv={{128,132},{125,128},{125,132},-1},f=2},
			{10,11,12,uv={{125,133},{120,128},{120,133},-1},f=3},
			{5 ,7 ,3 ,uv={{125,136},{125,133},{120,133},-1},f=2},
			{3 ,7 ,8 ,uv={{128,128},{125,128},{125,132},-1},f=2},
			{7 ,5 ,6 ,uv={{128,128},{125,128},{125,132},-1},f=2},
			{1 ,3 ,4 ,uv={{125,132},{128,132},{128,128},-1},f=2},
			{6 ,5 ,1 ,uv={{128,132},{128,128},{125,128},-1},f=2},
			{10,9 ,11,uv={{125,133},{125,128},{120,128},-1},f=3},
		},
		coll={{-6,0,-6,6,52,6}}
	},
	{--button +X (9)
		v={
			{-6   ,46  ,-6  },
			{-6   ,0   ,-6  },
			{-6   ,46  ,6   },
			{-6   ,0   ,6   },
			{6    ,51.2,-6  },
			{6    ,0   ,-6  },
			{6    ,51.2,6   },
			{6    ,0   ,6   },
			{4.5  ,51.2,4.5 },
			{4.5  ,51.2,-4.5},
			{-5.5 ,47.2,4.5 },
			{-5.5 ,47.2,-4.5},
		},
		f={
			{5 ,3 ,1 ,uv={{125,136},{120,133},{120,136},-1},f=2},
			{3 ,8 ,4 ,uv={{128,128},{125,132},{128,132},-1},f=2},
			{7 ,6 ,8 ,uv={{128,128},{125,132},{128,132},-1},f=2},
			{1 ,4 ,2 ,uv={{125,132},{128,128},{125,128},-1},f=2},
			{6 ,1 ,2 ,uv={{128,132},{125,128},{125,132},-1},f=2},
			{10,11,12,uv={{125,133},{120,128},{120,133},-1},f=3},
			{5 ,7 ,3 ,uv={{125,136},{125,133},{120,133},-1},f=2},
			{3 ,7 ,8 ,uv={{128,128},{125,128},{125,132},-1},f=2},
			{7 ,5 ,6 ,uv={{128,128},{125,128},{125,132},-1},f=2},
			{1 ,3 ,4 ,uv={{125,132},{128,132},{128,128},-1},f=2},
			{6 ,5 ,1 ,uv={{128,132},{128,128},{125,128},-1},f=2},
			{10,9 ,11,uv={{125,133},{125,128},{120,128},-1},f=3},
		},
		coll={{-6,0,-6,6,52,6}}
	},
	{--button -Z (10)
		v={
			{-6  ,46  ,6   },
			{-6  ,0   ,6   },
			{6   ,46  ,6   },
			{6   ,0   ,6   },
			{-6  ,51.2,-6  },
			{-6  ,0   ,-6  },
			{6   ,51.2,-6  },
			{6   ,0   ,-6  },
			{4.5 ,51.2,-4.5},
			{-4.5,51.2,-4.5},
			{4.5 ,47.2,5.5 },
			{-4.5,47.2,5.5 },
		},
		f={
			{5 ,3 ,1 ,uv={{125,136},{120,133},{120,136},-1},f=2},
			{3 ,8 ,4 ,uv={{128,128},{125,132},{128,132},-1},f=2},
			{7 ,6 ,8 ,uv={{128,128},{125,132},{128,132},-1},f=2},
			{1 ,4 ,2 ,uv={{125,132},{128,128},{125,128},-1},f=2},
			{6 ,1 ,2 ,uv={{128,132},{125,128},{125,132},-1},f=2},
			{10,11,12,uv={{125,133},{120,128},{120,133},-1},f=3},
			{5 ,7 ,3 ,uv={{125,136},{125,133},{120,133},-1},f=2},
			{3 ,7 ,8 ,uv={{128,128},{125,128},{125,132},-1},f=2},
			{7 ,5 ,6 ,uv={{128,128},{125,128},{125,132},-1},f=2},
			{1 ,3 ,4 ,uv={{125,132},{128,132},{128,128},-1},f=2},
			{6 ,5 ,1 ,uv={{128,132},{128,128},{125,128},-1},f=2},
			{10,9 ,11,uv={{125,133},{125,128},{120,128},-1},f=3},
		},
		coll={{-6,0,-6,6,52,6}}
	},
	{--button +Z (11)
		v={
			{6   ,46  ,-6   },
			{6   ,0   ,-6   },
			{-6  ,46  ,-6   },
			{-6  ,0   ,-6   },
			{6   ,51.2,6    },
			{6   ,0   ,6    },
			{-6  ,51.2,6    },
			{-6  ,0   ,6    },
			{-4.5,51.2,4.5  },
			{4.5 ,51.2,4.5  },
			{-4.5,47.2,-5.5 },
			{4.5 ,47.2,-5.5 },
		},
		f={
			{5 ,3 ,1 ,uv={{125,136},{120,133},{120,136},-1},f=2},
			{3 ,8 ,4 ,uv={{128,128},{125,132},{128,132},-1},f=2},
			{7 ,6 ,8 ,uv={{128,128},{125,132},{128,132},-1},f=2},
			{1 ,4 ,2 ,uv={{125,132},{128,128},{125,128},-1},f=2},
			{6 ,1 ,2 ,uv={{128,132},{125,128},{125,132},-1},f=2},
			{10,11,12,uv={{125,133},{120,128},{120,133},-1},f=3},
			{5 ,7 ,3 ,uv={{125,136},{125,133},{120,133},-1},f=2},
			{3 ,7 ,8 ,uv={{128,128},{125,128},{125,132},-1},f=2},
			{7 ,5 ,6 ,uv={{128,128},{125,128},{125,132},-1},f=2},
			{1 ,3 ,4 ,uv={{125,132},{128,132},{128,128},-1},f=2},
			{6 ,5 ,1 ,uv={{128,132},{128,128},{125,128},-1},f=2},
			{10,9 ,11,uv={{125,133},{125,128},{120,128},-1},f=3},
		},
		coll={{-6,0,-6,6,52,6}}
	},
	{ --turret -X (12)
		v={
			 {7,0  ,0},
			 {28,27 ,0},
			 {7,27 ,0},
			 {28,0  ,0},
			 {-24,0  ,-19},
			 {-4,27 ,-8},
			 {-24,27 ,-19},
			 {-4,0  ,-8},
			 {-24,0  ,18},
			 {-4,27 ,7},
			 {-24,27 ,18},
			 {-4,0  ,7},
			 {12,41 ,-12},
			 {8,12 ,-9},
			 {-9,67 ,-9},
			 {-12,41 ,-12},
			 {-9,12 ,-9},
			 {0,76 ,0},
			 {-9,67 ,8},
			 {-12,41 ,12},
			 {-9,12 ,8},
			 {8,67 ,8},
			 {12,41 ,12},
			 {8,12 ,8},
			 {8,67 ,-9},
			 {-12,37 ,0},
			 {-12,42 ,4},
			 {-12,42 ,-5},
			 {-12,47 ,0},
			 {12,41 ,-22},
			 {8,12 ,-19},
			 {-9,67 ,-19},
			 {-12,41 ,-22},
			 {-9,12 ,-19},
			 {8,67 ,-19},
			 {-9,67 ,18},
			 {-12,41 ,22},
			 {-9,12 ,18},
			 {8,67 ,18},
			 {12,41 ,22},
			 {8,12 ,18},
			 {0,28 ,20},
			 {0,55 ,20},
			 {0,28 ,-20},
			 {0,55 ,-20},
			 {0,43 ,-22},
			 {0,43 ,21},
		},
		f={
			{3 ,4 ,1 ,uv={{124,138},{120,144},{124,144},-1},f=3},
			{7 ,8 ,5 ,uv={{120,138},{124,144},{120,144},-1},f=3},
			{11,12,9 ,uv={{120,138},{124,144},{120,144},-1},f=3},
			{45,47,46,uv={{124,138},{123,136},{123,138},-1},f=3},
			{44,47,42,uv={{122,138},{123,136},{122,136},-1},f=3},
			{3 ,2 ,4 ,uv={{124,138},{120,138},{120,144},-1},f=3},
			{7 ,6 ,8 ,uv={{120,138},{124,138},{124,144},-1},f=3},
			{11,10,12,uv={{120,138},{124,138},{124,144},-1},f=3},
			{45,43,47,uv={{124,138},{124,136},{123,136},-1},f=3},
			{44,46,47,uv={{122,138},{123,138},{123,136},-1},f=3},
			{25,18,15,uv={{126,138},{128,138},{128,136},-1},f=2},
			{25,16,13,uv={{125,140},{125,140},{126,139},-1},f=2},
			{13,17,14,uv={{125,140},{125,140},{126,139},-1},f=2},
			{15,20,16,uv={{124,138},{124,139},{125,138},-1},f=2},
			{17,20,21,uv={{124,138},{124,139},{125,138},-1},f=2},
			{15,18,19,uv={{124,138},{124,139},{125,138},-1},f=2},
			{20,22,23,uv={{125,140},{125,140},{126,139},-1},f=2},
			{21,23,24,uv={{125,140},{125,140},{126,139},-1},f=2},
			{19,18,22,uv={{124,138},{124,139},{125,138},-1},f=2},
			{22,18,25,uv={{124,138},{124,139},{125,138},-1},f=2},
			{22,13,23,uv={{124,138},{124,139},{125,138},-1},f=2},
			{23,14,24,uv={{124,138},{124,139},{125,138},-1},f=2},
			{25,15,16,uv={{125,140},{125,140},{126,139},-1},f=2},
			{13,16,17,uv={{125,140},{125,140},{126,139},-1},f=2},
			{15,19,20,uv={{124,138},{124,139},{125,138},-1},f=2},
			{17,16,20,uv={{124,138},{124,139},{125,138},-1},f=2},
			{20,19,22,uv={{125,140},{125,140},{126,139},-1},f=2},
			{21,20,23,uv={{125,140},{125,140},{126,139},-1},f=2},
			{22,25,13,uv={{124,138},{124,139},{125,138},-1},f=2},
			{23,13,14,uv={{124,138},{124,139},{125,138},-1},f=2},
			{35,33,30,uv={{128,136},{124,140},{128,140},-1},f=3},
			{30,34,31,uv={{128,143},{124,140},{124,143},-1},f=3},
			{36,40,37,uv={{128,136},{124,140},{128,140},-1},f=3},
			{38,40,41,uv={{128,143},{124,140},{124,143},-1},f=3},
			{35,32,33,uv={{128,136},{124,136},{124,140},-1},f=3},
			{30,33,34,uv={{128,143},{128,140},{124,140},-1},f=3},
			{36,39,40,uv={{128,136},{124,136},{124,140},-1},f=3},
			{38,37,40,uv={{128,143},{128,140},{124,140},-1},f=3},
			{29,26,28,uv={{122,138},{120,136},{120,138},-1},f=2},
			{29,27,26,uv={{122,138},{122,136},{120,136},-1},f=2},
		},
		coll={{-12,0,-12,12,69,12}}
	},
	{ --turret +X (13)
		v={
			 {-7,0,0},
			 {-28,27,0},
			 {-7,27,0},
			 {-28,0,0},
			 {24,0,19},
			 {4,27,8},
			 {24,27,19},
			 {4,0,8},
			 {24,0,-18},
			 {4,27,-7},
			 {24,27,-18},
			 {4,0,-7},
			 {-12,41,12},
			 {-8,12,9},
			 {9,67,9},
			 {12,41,12},
			 {9,12,9},
			 {0,76,0},
			 {9,67,-8},
			 {12,41,-12},
			 {9,12,-8},
			 {-8,67,-8},
			 {-12,41,-12},
			 {-8,12,-8},
			 {-8,67,9},
			 {12,37,0},
			 {12,42,-4},
			 {12,42,5},
			 {12,47,0},
			 {-12,41,22},
			 {-8,12,19},
			 {9,67,19},
			 {12,41,22},
			 {9,12,19},
			 {-8,67,19},
			 {9,67,-18},
			 {12,41,-22},
			 {9,12,-18},
			 {-8,67,-18},
			 {-12,41,-22},
			 {-8,12,-18},
			 {0,28,-20},
			 {0,55,-20},
			 {0,28,20},
			 {0,55,20},
			 {0,43,22},
			 {0,43,-21},
		},
		f={
			{3 ,4 ,1 ,uv={{124,138},{120,144},{124,144},-1},f=3},
			{7 ,8 ,5 ,uv={{120,138},{124,144},{120,144},-1},f=3},
			{11,12,9 ,uv={{120,138},{124,144},{120,144},-1},f=3},
			{45,47,46,uv={{124,138},{123,136},{123,138},-1},f=3},
			{44,47,42,uv={{122,138},{123,136},{122,136},-1},f=3},
			{3 ,2 ,4 ,uv={{124,138},{120,138},{120,144},-1},f=3},
			{7 ,6 ,8 ,uv={{120,138},{124,138},{124,144},-1},f=3},
			{11,10,12,uv={{120,138},{124,138},{124,144},-1},f=3},
			{45,43,47,uv={{124,138},{124,136},{123,136},-1},f=3},
			{44,46,47,uv={{122,138},{123,138},{123,136},-1},f=3},
			{25,18,15,uv={{126,138},{128,138},{128,136},-1},f=2},
			{25,16,13,uv={{125,140},{125,140},{126,139},-1},f=2},
			{13,17,14,uv={{125,140},{125,140},{126,139},-1},f=2},
			{15,20,16,uv={{124,138},{124,139},{125,138},-1},f=2},
			{17,20,21,uv={{124,138},{124,139},{125,138},-1},f=2},
			{15,18,19,uv={{124,138},{124,139},{125,138},-1},f=2},
			{20,22,23,uv={{125,140},{125,140},{126,139},-1},f=2},
			{21,23,24,uv={{125,140},{125,140},{126,139},-1},f=2},
			{19,18,22,uv={{124,138},{124,139},{125,138},-1},f=2},
			{22,18,25,uv={{124,138},{124,139},{125,138},-1},f=2},
			{22,13,23,uv={{124,138},{124,139},{125,138},-1},f=2},
			{23,14,24,uv={{124,138},{124,139},{125,138},-1},f=2},
			{25,15,16,uv={{125,140},{125,140},{126,139},-1},f=2},
			{13,16,17,uv={{125,140},{125,140},{126,139},-1},f=2},
			{15,19,20,uv={{124,138},{124,139},{125,138},-1},f=2},
			{17,16,20,uv={{124,138},{124,139},{125,138},-1},f=2},
			{20,19,22,uv={{125,140},{125,140},{126,139},-1},f=2},
			{21,20,23,uv={{125,140},{125,140},{126,139},-1},f=2},
			{22,25,13,uv={{124,138},{124,139},{125,138},-1},f=2},
			{23,13,14,uv={{124,138},{124,139},{125,138},-1},f=2},
			{35,33,30,uv={{128,136},{124,140},{128,140},-1},f=3},
			{30,34,31,uv={{128,143},{124,140},{124,143},-1},f=3},
			{36,40,37,uv={{128,136},{124,140},{128,140},-1},f=3},
			{38,40,41,uv={{128,143},{124,140},{124,143},-1},f=3},
			{35,32,33,uv={{128,136},{124,136},{124,140},-1},f=3},
			{30,33,34,uv={{128,143},{128,140},{124,140},-1},f=3},
			{36,39,40,uv={{128,136},{124,136},{124,140},-1},f=3},
			{38,37,40,uv={{128,143},{128,140},{124,140},-1},f=3},
			{29,26,28,uv={{122,138},{120,136},{120,138},-1},f=2},
			{29,27,26,uv={{122,138},{122,136},{120,136},-1},f=2},
		},
		coll={{-12,0,-12,12,69,12}}
	},
	{ --turret -Z (14)
		v={
			{0  ,0  ,7},
			{0  ,27 ,28},
			{0  ,27 ,7},
			{0  ,0  ,28},
			{19 ,0  ,-24},
			{8  ,27 ,-4},
			{19 ,27 ,-24},
			{8  ,0  ,-4},
			{-18,0  ,-24},
			{-7 ,27 ,-4},
			{-18,27 ,-24},
			{-7 ,0  ,-4},
			{12 ,41 ,12},
			{9  ,12 ,8},
			{9  ,67 ,-9},
			{12 ,41 ,-12},
			{9  ,12 ,-9},
			{0  ,76 ,0},
			{-8 ,67 ,-9},
			{-12,41 ,-12},
			{-8 ,12 ,-9},
			{-8 ,67 ,8},
			{-12,41 ,12},
			{-8 ,12 ,8},
			{9  ,67 ,8},
			{0  ,37 ,-12},
			{-4 ,42 ,-12},
			{5  ,42 ,-12},
			{0  ,47 ,-12},
			{22 ,41 ,12},
			{19 ,12 ,8},
			{19 ,67 ,-9},
			{22 ,41 ,-12},
			{19 ,12 ,-9},
			{19 ,67 ,8},
			{-18,67 ,-9},
			{-22,41 ,-12},
			{-18,12 ,-9},
			{-18,67 ,8},
			{-22,41 ,12},
			{-18,12 ,8},
			{-20,28 ,0},
			{-20,55 ,0},
			{20 ,28 ,0},
			{20 ,55 ,0},
			{22 ,43 ,0},
			{-21,43 ,0},
		},
		f={
			{3 ,4 ,1 ,uv={{124,138},{120,144},{124,144},-1},f=3},
			{7 ,8 ,5 ,uv={{120,138},{124,144},{120,144},-1},f=3},
			{11,12,9 ,uv={{120,138},{124,144},{120,144},-1},f=3},
			{45,47,46,uv={{124,138},{123,136},{123,138},-1},f=3},
			{44,47,42,uv={{122,138},{123,136},{122,136},-1},f=3},
			{3 ,2 ,4 ,uv={{124,138},{120,138},{120,144},-1},f=3},
			{7 ,6 ,8 ,uv={{120,138},{124,138},{124,144},-1},f=3},
			{11,10,12,uv={{120,138},{124,138},{124,144},-1},f=3},
			{45,43,47,uv={{124,138},{124,136},{123,136},-1},f=3},
			{44,46,47,uv={{122,138},{123,138},{123,136},-1},f=3},
			{25,18,15,uv={{126,138},{128,138},{128,136},-1},f=2},
			{25,16,13,uv={{125,140},{125,140},{126,139},-1},f=2},
			{13,17,14,uv={{125,140},{125,140},{126,139},-1},f=2},
			{15,20,16,uv={{124,138},{124,139},{125,138},-1},f=2},
			{17,20,21,uv={{124,138},{124,139},{125,138},-1},f=2},
			{15,18,19,uv={{124,138},{124,139},{125,138},-1},f=2},
			{20,22,23,uv={{125,140},{125,140},{126,139},-1},f=2},
			{21,23,24,uv={{125,140},{125,140},{126,139},-1},f=2},
			{19,18,22,uv={{124,138},{124,139},{125,138},-1},f=2},
			{22,18,25,uv={{124,138},{124,139},{125,138},-1},f=2},
			{22,13,23,uv={{124,138},{124,139},{125,138},-1},f=2},
			{23,14,24,uv={{124,138},{124,139},{125,138},-1},f=2},
			{25,15,16,uv={{125,140},{125,140},{126,139},-1},f=2},
			{13,16,17,uv={{125,140},{125,140},{126,139},-1},f=2},
			{15,19,20,uv={{124,138},{124,139},{125,138},-1},f=2},
			{17,16,20,uv={{124,138},{124,139},{125,138},-1},f=2},
			{20,19,22,uv={{125,140},{125,140},{126,139},-1},f=2},
			{21,20,23,uv={{125,140},{125,140},{126,139},-1},f=2},
			{22,25,13,uv={{124,138},{124,139},{125,138},-1},f=2},
			{23,13,14,uv={{124,138},{124,139},{125,138},-1},f=2},
			{35,33,30,uv={{128,136},{124,140},{128,140},-1},f=3},
			{30,34,31,uv={{128,143},{124,140},{124,143},-1},f=3},
			{36,40,37,uv={{128,136},{124,140},{128,140},-1},f=3},
			{38,40,41,uv={{128,143},{124,140},{124,143},-1},f=3},
			{35,32,33,uv={{128,136},{124,136},{124,140},-1},f=3},
			{30,33,34,uv={{128,143},{128,140},{124,140},-1},f=3},
			{36,39,40,uv={{128,136},{124,136},{124,140},-1},f=3},
			{38,37,40,uv={{128,143},{128,140},{124,140},-1},f=3},
			{29,26,28,uv={{122,138},{120,136},{120,138},-1},f=2},
			{29,27,26,uv={{122,138},{122,136},{120,136},-1},f=2},
		},
		coll={{-12,0,-12,12,69,12}}
	},
	{ --turret +Z (15)
		v={
			 {0,0  ,-7 },
			 {0,27 ,-28},
			 {0,27 ,-7 },
			 {0,0  ,-28},
			 {-19,0  ,24 },
			 {-8,27 ,4  },
			 {-19,27 ,24 },
			 {-8,0  ,4  },
			 {18,0  ,24 },
			 {7,27 ,4  },
			 {18,27 ,24 },
			 {7,0  ,4  },
			 {-12,41 ,-12},
			 {-9,12 ,-8 },
			 {-9,67 ,9  },
			 {-12,41 ,12 },
			 {-9,12 ,9  },
			 {0,76 ,0  },
			 {8,67 ,9  },
			 {12,41 ,12 },
			 {8,12 ,9  },
			 {8,67 ,-8 },
			 {12,41 ,-12},
			 {8,12 ,-8 },
			 {-9,67 ,-8 },
			 {0,37 ,12 },
			 {4,42 ,12 },
			 {-5,42 ,12 },
			 {0,47 ,12 },
			 {-22,41 ,-12},
			 {-19,12 ,-8 },
			 {-19,67 ,9  },
			 {-22,41 ,12 },
			 {-19,12 ,9  },
			 {-19,67 ,-8 },
			 {18,67 ,9  },
			 {22,41 ,12 },
			 {18,12 ,9  },
			 {18,67 ,-8 },
			 {22,41 ,-12},
			 {18,12 ,-8 },
			 {20,28 ,0  },
			 {20,55 ,0  },
			 {-20,28 ,0  },
			 {-20,55 ,0  },
			 {-22,43 ,0  },
			 {21,43 ,0  },
		},
		f={
			{3 ,4 ,1 ,uv={{124,138},{120,144},{124,144},-1},f=3},
			{7 ,8 ,5 ,uv={{120,138},{124,144},{120,144},-1},f=3},
			{11,12,9 ,uv={{120,138},{124,144},{120,144},-1},f=3},
			{45,47,46,uv={{124,138},{123,136},{123,138},-1},f=3},
			{44,47,42,uv={{122,138},{123,136},{122,136},-1},f=3},
			{3 ,2 ,4 ,uv={{124,138},{120,138},{120,144},-1},f=3},
			{7 ,6 ,8 ,uv={{120,138},{124,138},{124,144},-1},f=3},
			{11,10,12,uv={{120,138},{124,138},{124,144},-1},f=3},
			{45,43,47,uv={{124,138},{124,136},{123,136},-1},f=3},
			{44,46,47,uv={{122,138},{123,138},{123,136},-1},f=3},
			{25,18,15,uv={{126,138},{128,138},{128,136},-1},f=2},
			{25,16,13,uv={{125,140},{125,140},{126,139},-1},f=2},
			{13,17,14,uv={{125,140},{125,140},{126,139},-1},f=2},
			{15,20,16,uv={{124,138},{124,139},{125,138},-1},f=2},
			{17,20,21,uv={{124,138},{124,139},{125,138},-1},f=2},
			{15,18,19,uv={{124,138},{124,139},{125,138},-1},f=2},
			{20,22,23,uv={{125,140},{125,140},{126,139},-1},f=2},
			{21,23,24,uv={{125,140},{125,140},{126,139},-1},f=2},
			{19,18,22,uv={{124,138},{124,139},{125,138},-1},f=2},
			{22,18,25,uv={{124,138},{124,139},{125,138},-1},f=2},
			{22,13,23,uv={{124,138},{124,139},{125,138},-1},f=2},
			{23,14,24,uv={{124,138},{124,139},{125,138},-1},f=2},
			{25,15,16,uv={{125,140},{125,140},{126,139},-1},f=2},
			{13,16,17,uv={{125,140},{125,140},{126,139},-1},f=2},
			{15,19,20,uv={{124,138},{124,139},{125,138},-1},f=2},
			{17,16,20,uv={{124,138},{124,139},{125,138},-1},f=2},
			{20,19,22,uv={{125,140},{125,140},{126,139},-1},f=2},
			{21,20,23,uv={{125,140},{125,140},{126,139},-1},f=2},
			{22,25,13,uv={{124,138},{124,139},{125,138},-1},f=2},
			{23,13,14,uv={{124,138},{124,139},{125,138},-1},f=2},
			{35,33,30,uv={{128,136},{124,140},{128,140},-1},f=3},
			{30,34,31,uv={{128,143},{124,140},{124,143},-1},f=3},
			{36,40,37,uv={{128,136},{124,140},{128,140},-1},f=3},
			{38,40,41,uv={{128,143},{124,140},{124,143},-1},f=3},
			{35,32,33,uv={{128,136},{124,136},{124,140},-1},f=3},
			{30,33,34,uv={{128,143},{128,140},{124,140},-1},f=3},
			{36,39,40,uv={{128,136},{124,136},{124,140},-1},f=3},
			{38,37,40,uv={{128,143},{128,140},{124,140},-1},f=3},
			{29,26,28,uv={{122,138},{120,136},{120,138},-1},f=2},
			{29,27,26,uv={{122,138},{122,136},{120,136},-1},f=2},
		},
		coll={{-12,0,-12,12,69,12}}
	},
	{ --Floor button (16)
		v={
			 {-32.4,4  ,-32.4},
			 {-36.9,0  ,-36.9},
			 {-32.4,4  ,32.4},
			 {-36.9,0  ,36.9},
			 {32.4,4  ,-32.4},
			 {36.9,0  ,-36.9},
			 {32.4,4  ,32.4},
			 {36.9,0  ,36.9},
			 {-33.3,5  ,-5.4},
			 {-36.9,2  ,-5.4},
			 {-33.3,5  ,5.4},
			 {-36.9,2  ,5.4},
			 {33.3,5  ,-5.4},
			 {36.9,2  ,-5.4},
			 {33.3,5  ,5.4},
			 {36.9,2  ,5.4},
		},
		f={ 
			 {2 ,3 ,1 ,uv={{32,248},{31,246},{31,248},-1},f=1},
			 {4 ,7 ,3 ,uv={{32,248},{31,246},{31,248},-1},f=1},
			 {8 ,5 ,7 ,uv={{31,248},{32,246},{31,248},-1},f=1},
			 {6 ,1 ,5 ,uv={{32,248},{31,246},{31,248},-1},f=1},
			 {7 ,1 ,3 ,uv={{31,247},{16,232},{16,247},-1},f=1},
			 {2 ,4 ,3 ,uv={{32,248},{32,246},{31,246},-1},f=1},
			 {4 ,8 ,7 ,uv={{32,248},{32,246},{31,246},-1},f=1},
			 {8 ,6 ,5 ,uv={{31,248},{32,246},{31,246},-1},f=1},
			 {6 ,2 ,1 ,uv={{32,248},{32,246},{31,246},-1},f=1},
			 {7 ,5 ,1 ,uv={{31,247},{31,232},{16,232},-1},f=1},
			 {10,11,9 ,uv={{16,248},{22,247},{16,247},-1},f=1},
			 {16,13,15,uv={{16,248},{22,247},{16,247},-1},f=1},
			 {10,12,11,uv={{16,248},{22,248},{22,247},-1},f=1},
			 {16,14,13,uv={{16,248},{22,248},{22,247},-1},f=1},
		},
		coll={{-36,0,-36,36,5,36}}
	},
	{ --lift -X (17)
	v={
			{96   ,128 ,-96 },
			{96   ,0   ,0   },
			{96   ,0   ,-96 },
			{0    ,0   ,-96 },
			{96   ,0   ,96  },
			{0    ,0   ,96  },
			{-96  ,0   ,-96 },
			{0    ,0   ,0   },
			{-96  ,0   ,96  },
			{-96  ,0   ,0   },
			{-96  ,128 ,96  },
			{-96  ,0   ,47  },
			{-192 ,128 ,48  },
			{-192 ,128 ,-48 },
			{-192 ,0   ,-48 },
			{-192 ,0   ,48  },
			{96   ,128 ,0   },
			{96   ,128 ,96  },
			{0    ,128 ,-96 },
			{0    ,128 ,0   },
			{0    ,128 ,96  },
			{-96  ,128 ,0   },
			{-96  ,128 ,-96 },
			{-96  ,128 ,-48 },
			{-96  ,0   ,-48 },
			{-66  ,128 ,-96 },
			{-66  ,0   ,-96 },
			{-48  ,128 ,96  },
			{-48  ,0   ,96  },
			{-96  ,128 ,48  },
	},
	f={
		{19,3,4,uv={{48,0},{24,32},{48,32},-1},f=2},
		{18,6,5,uv={{48,0},{24,32},{48,32},-1},f=2},
		{23,4,7,uv={{48,0},{24,32},{48,32},-1},f=2},
		{21,9,6,uv={{48,0},{24,32},{48,32},-1},f=2},
		{24,27,25,uv={{48,0},{35,32},{48,32},-1},f=2},
		{28,12,29,uv={{40,0},{24,32},{40,32},-1},f=2},
		{19,1,3,uv={{48,0},{24,0},{24,32},-1},f=2},
		{18,21,6,uv={{48,0},{24,0},{24,32},-1},f=2},
		{23,19,4,uv={{48,0},{24,0},{24,32},-1},f=2},
		{21,11,9,uv={{48,0},{24,0},{24,32},-1},f=2},
		{24,26,27,uv={{48,0},{35,0},{35,32},-1},f=2},
		{28,30,12,uv={{40,0},{24,0},{24,32},-1},f=2},
		{8,3,2,uv={{120,120},{96,96},{96,120},-1},f=2},
		{6,2,5,uv={{120,120},{96,96},{96,120},-1},f=2},
		{10,4,8,uv={{120,120},{96,96},{96,120},-1},f=2},
		{9,8,6,uv={{120,120},{96,96},{96,120},-1},f=2},
		{16,25,12,uv={{120,120},{96,96},{96,120},-1},f=2},
		{30,16,12,uv={{72,96},{48,128},{72,128},-1},f=2},
		{17,21,18,uv={{96,120},{120,96},{96,96},-1},f=2},
		{1,20,17,uv={{96,120},{120,96},{96,96},-1},f=2},
		{22,21,20,uv={{120,120},{96,96},{96,120},-1},f=2},
		{19,22,20,uv={{96,120},{120,96},{96,96},-1},f=2},
		{14,30,24,uv={{120,120},{96,96},{96,120},-1},f=2},
		{8,4,3,uv={{120,120},{120,96},{96,96},-1},f=2},
		{6,8,2,uv={{120,120},{120,96},{96,96},-1},f=2},
		{10,7,4,uv={{120,120},{120,96},{96,96},-1},f=2},
		{9,10,8,uv={{120,120},{120,96},{96,96},-1},f=2},
		{16,15,25,uv={{120,120},{120,96},{96,96},-1},f=2},
		{30,13,16,uv={{72,96},{48,96},{48,128},-1},f=2},
		{17,20,21,uv={{96,120},{120,120},{120,96},-1},f=2},
		{1,19,20,uv={{96,120},{120,120},{120,96},-1},f=2},
		{22,11,21,uv={{120,120},{120,96},{96,96},-1},f=2},
		{19,23,22,uv={{96,120},{120,120},{120,96},-1},f=2},
		{14,13,30,uv={{120,120},{120,96},{96,96},-1},f=2},
		{16,14,15,uv={{72,128},{48,96},{48,128},-1},f=2},
		{14,25,15,uv={{72,96},{48,128},{72,128},-1},f=2},
		{30,25,12,uv={{96,96},{72,128},{96,128},-1},f=3},
		{16,13,14,uv={{72,128},{72,96},{48,96},-1},f=2},
		{14,24,25,uv={{72,96},{48,96},{48,128},-1},f=2},
		{30,24,25,uv={{96,96},{72,96},{72,128},-1},f=3},
	},
	coll={
		{-96,0  ,-96,96,0  ,96},
		{-96,128,-96,96,128,96},
		--
		{-96 ,0  ,-96, 96 ,128,-96},
		{-96 ,0  , 96, 96 ,128, 96},
		{-96 ,0  ,-96,-96 ,128,-48},
		{-96 ,0  , 48,-96 ,128, 96},
		{-192,0  ,-48,-96 ,0  , 48},
		{-192,128,-48,-96 ,128, 48},
		{-192,0  ,-48,-192,128, 48},
		{-192,0  ,-48,-96 ,128,-48},
		{-192,0  , 48,-96 ,128, 48}
	}
	},
	{ --lift +X (18)
	v={
			{-96,128 ,96},
			{-96,0   ,0},
			{-96,0   ,96},
			{0,0   ,96},
			{-96,0   ,-96},
			{0,0   ,-96},
			{96,0   ,96},
			{0,0   ,0},
			{96,0   ,-96},
			{96,0   ,0},
			{96,128 ,-96},
			{96,0   ,-47},
			{192,128 ,-48},
			{192,128 ,48},
			{192,0   ,48},
			{192,0   ,-48},
			{-96,128 ,0},
			{-96,128 ,-96},
			{0,128 ,96},
			{0,128 ,0},
			{0,128 ,-96},
			{96,128 ,0},
			{96,128 ,96},
			{96,128 ,48},
			{96,0   ,48},
			{66,128 ,96},
			{66,0   ,96},
			{48,128 ,-96},
			{48,0   ,-96},
			{96,128 ,-48},
	},
	f={
		{19,3,4,uv={{48,0},{24,32},{48,32},-1},f=2},
		{18,6,5,uv={{48,0},{24,32},{48,32},-1},f=2},
		{23,4,7,uv={{48,0},{24,32},{48,32},-1},f=2},
		{21,9,6,uv={{48,0},{24,32},{48,32},-1},f=2},
		{24,27,25,uv={{48,0},{35,32},{48,32},-1},f=2},
		{28,12,29,uv={{40,0},{24,32},{40,32},-1},f=2},
		{19,1,3,uv={{48,0},{24,0},{24,32},-1},f=2},
		{18,21,6,uv={{48,0},{24,0},{24,32},-1},f=2},
		{23,19,4,uv={{48,0},{24,0},{24,32},-1},f=2},
		{21,11,9,uv={{48,0},{24,0},{24,32},-1},f=2},
		{24,26,27,uv={{48,0},{35,0},{35,32},-1},f=2},
		{28,30,12,uv={{40,0},{24,0},{24,32},-1},f=2},
		{8,3,2,uv={{120,120},{96,96},{96,120},-1},f=2},
		{6,2,5,uv={{120,120},{96,96},{96,120},-1},f=2},
		{10,4,8,uv={{120,120},{96,96},{96,120},-1},f=2},
		{9,8,6,uv={{120,120},{96,96},{96,120},-1},f=2},
		{16,25,12,uv={{120,120},{96,96},{96,120},-1},f=2},
		{30,16,12,uv={{72,96},{48,128},{72,128},-1},f=2},
		{17,21,18,uv={{96,120},{120,96},{96,96},-1},f=2},
		{1,20,17,uv={{96,120},{120,96},{96,96},-1},f=2},
		{22,21,20,uv={{120,120},{96,96},{96,120},-1},f=2},
		{19,22,20,uv={{96,120},{120,96},{96,96},-1},f=2},
		{14,30,24,uv={{120,120},{96,96},{96,120},-1},f=2},
		{8,4,3,uv={{120,120},{120,96},{96,96},-1},f=2},
		{6,8,2,uv={{120,120},{120,96},{96,96},-1},f=2},
		{10,7,4,uv={{120,120},{120,96},{96,96},-1},f=2},
		{9,10,8,uv={{120,120},{120,96},{96,96},-1},f=2},
		{16,15,25,uv={{120,120},{120,96},{96,96},-1},f=2},
		{30,13,16,uv={{72,96},{48,96},{48,128},-1},f=2},
		{17,20,21,uv={{96,120},{120,120},{120,96},-1},f=2},
		{1,19,20,uv={{96,120},{120,120},{120,96},-1},f=2},
		{22,11,21,uv={{120,120},{120,96},{96,96},-1},f=2},
		{19,23,22,uv={{96,120},{120,120},{120,96},-1},f=2},
		{14,13,30,uv={{120,120},{120,96},{96,96},-1},f=2},
		{16,14,15,uv={{72,128},{48,96},{48,128},-1},f=2},
		{14,25,15,uv={{72,96},{48,128},{72,128},-1},f=2},
		{30,25,12,uv={{96,96},{72,128},{96,128},-1},f=3},
		{16,13,14,uv={{72,128},{72,96},{48,96},-1},f=2},
		{14,24,25,uv={{72,96},{48,96},{48,128},-1},f=2},
		{30,24,25,uv={{96,96},{72,96},{72,128},-1},f=3},
	},
	coll={
		{-96,0  ,-96,96,0  ,96},
		{-96,128,-96,96,128,96},
		--
		{-96 ,0  ,-96, 96 ,128,-96},
		{-96 ,0  , 96, 96 ,128, 96},
		{ 96 ,0  ,-96, 96 ,128,-48},
		{ 96 ,0  , 48, 96 ,128, 96},
		{ 96 ,0  ,-48, 192,0  , 48},
		{ 96 ,128,-48, 192,128, 48},
		{ 192,0  ,-48, 192,128, 48},
		{ 96 ,0  ,-48, 192,128,-48},
		{ 96 ,0  , 48, 192,128, 48}
	}
	},
	{ --lift -Z (19)
	v={
			{-96 ,128 ,-96},
			{0   ,0   ,-96},
			{-96 ,0   ,-96},
			{-96 ,0   ,0},
			{96  ,0   ,-96},
			{96  ,0   ,0},
			{-96 ,0   ,96},
			{0   ,0   ,0},
			{96  ,0   ,96},
			{0   ,0   ,96},
			{96  ,128 ,96},
			{47  ,0   ,96},
			{48  ,128 ,192},
			{-48 ,128 ,192},
			{-48 ,0   ,192},
			{48  ,0   ,192},
			{0   ,128 ,-96},
			{96  ,128 ,-96},
			{-96 ,128 ,0},
			{0   ,128 ,0},
			{96  ,128 ,0},
			{0   ,128 ,96},
			{-96 ,128 ,96},
			{-48 ,128 ,96},
			{-48 ,0   ,96},
			{-96 ,128 ,66},
			{-96 ,0   ,66},
			{96  ,128 ,48},
			{96  ,0   ,48},
			{48  ,128 ,96},
	},
	f={
		{19,3,4,uv={{48,0},{24,32},{48,32},-1},f=2},
		{18,6,5,uv={{48,0},{24,32},{48,32},-1},f=2},
		{23,4,7,uv={{48,0},{24,32},{48,32},-1},f=2},
		{21,9,6,uv={{48,0},{24,32},{48,32},-1},f=2},
		{24,27,25,uv={{48,0},{35,32},{48,32},-1},f=2},
		{28,12,29,uv={{40,0},{24,32},{40,32},-1},f=2},
		{19,1,3,uv={{48,0},{24,0},{24,32},-1},f=2},
		{18,21,6,uv={{48,0},{24,0},{24,32},-1},f=2},
		{23,19,4,uv={{48,0},{24,0},{24,32},-1},f=2},
		{21,11,9,uv={{48,0},{24,0},{24,32},-1},f=2},
		{24,26,27,uv={{48,0},{35,0},{35,32},-1},f=2},
		{28,30,12,uv={{40,0},{24,0},{24,32},-1},f=2},
		{8,3,2,uv={{120,120},{96,96},{96,120},-1},f=2},
		{6,2,5,uv={{120,120},{96,96},{96,120},-1},f=2},
		{10,4,8,uv={{120,120},{96,96},{96,120},-1},f=2},
		{9,8,6,uv={{120,120},{96,96},{96,120},-1},f=2},
		{16,25,12,uv={{120,120},{96,96},{96,120},-1},f=2},
		{30,16,12,uv={{72,96},{48,128},{72,128},-1},f=2},
		{17,21,18,uv={{96,120},{120,96},{96,96},-1},f=2},
		{1,20,17,uv={{96,120},{120,96},{96,96},-1},f=2},
		{22,21,20,uv={{120,120},{96,96},{96,120},-1},f=2},
		{19,22,20,uv={{96,120},{120,96},{96,96},-1},f=2},
		{14,30,24,uv={{120,120},{96,96},{96,120},-1},f=2},
		{8,4,3,uv={{120,120},{120,96},{96,96},-1},f=2},
		{6,8,2,uv={{120,120},{120,96},{96,96},-1},f=2},
		{10,7,4,uv={{120,120},{120,96},{96,96},-1},f=2},
		{9,10,8,uv={{120,120},{120,96},{96,96},-1},f=2},
		{16,15,25,uv={{120,120},{120,96},{96,96},-1},f=2},
		{30,13,16,uv={{72,96},{48,96},{48,128},-1},f=2},
		{17,20,21,uv={{96,120},{120,120},{120,96},-1},f=2},
		{1,19,20,uv={{96,120},{120,120},{120,96},-1},f=2},
		{22,11,21,uv={{120,120},{120,96},{96,96},-1},f=2},
		{19,23,22,uv={{96,120},{120,120},{120,96},-1},f=2},
		{14,13,30,uv={{120,120},{120,96},{96,96},-1},f=2},
		{16,14,15,uv={{72,128},{48,96},{48,128},-1},f=2},
		{14,25,15,uv={{72,96},{48,128},{72,128},-1},f=2},
		{30,25,12,uv={{96,96},{72,128},{96,128},-1},f=3},
		{16,13,14,uv={{72,128},{72,96},{48,96},-1},f=2},
		{14,24,25,uv={{72,96},{48,96},{48,128},-1},f=2},
		{30,24,25,uv={{96,96},{72,96},{72,128},-1},f=3},
	},
	coll={
		{-96,0  ,-96,96,0  ,96},
		{-96,128,-96,96,128,96},
		--
		{-96,0  ,-96 ,-96,128,96 },
		{ 96,0  ,-96 , 96,128,96 },
		{-96,0  , 96 ,-48,128,96 },
		{ 48,0  , 96 , 96,128,96 },
		{-48,0  , 96 , 48,0  ,192},
		{-48,128, 96 , 48,128,192},
		{-48,0  , 192, 48,128,192},
		{-48,0  , 96 ,-48,128,192},
		{ 48,0  , 96 , 48,128,192}
	}
	},
	{ --lift +Z (20)
	v={
			{96,128 ,96  },
			{0,0   ,96  },
			{96,0   ,96  },
			{96,0   ,0   },
			{-96,0   ,96  },
			{-96,0   ,0   },
			{96,0   ,-96 },
			{0,0   ,0   },
			{-96,0   ,-96 },
			{0,0   ,-96 },
			{-96,128 ,-96 },
			{-47,0   ,-96 },
			{-48,128 ,-192},
			{48,128 ,-192},
			{48,0   ,-192},
			{-48,0   ,-192},
			{0,128 ,96  },
			{-96,128 ,96  },
			{96,128 ,0   },
			{0,128 ,0   },
			{-96,128 ,0   },
			{0,128 ,-96 },
			{96,128 ,-96 },
			{48,128 ,-96 },
			{48,0   ,-96 },
			{96,128 ,-66 },
			{96,0   ,-66 },
			{-96,128 ,-48 },
			{-96,0   ,-48 },
			{-48,128 ,-96 },
	},
	f={
		{19,3,4,uv={{48,0},{24,32},{48,32},-1},f=2},
		{18,6,5,uv={{48,0},{24,32},{48,32},-1},f=2},
		{23,4,7,uv={{48,0},{24,32},{48,32},-1},f=2},
		{21,9,6,uv={{48,0},{24,32},{48,32},-1},f=2},
		{24,27,25,uv={{48,0},{35,32},{48,32},-1},f=2},
		{28,12,29,uv={{40,0},{24,32},{40,32},-1},f=2},
		{19,1,3,uv={{48,0},{24,0},{24,32},-1},f=2},
		{18,21,6,uv={{48,0},{24,0},{24,32},-1},f=2},
		{23,19,4,uv={{48,0},{24,0},{24,32},-1},f=2},
		{21,11,9,uv={{48,0},{24,0},{24,32},-1},f=2},
		{24,26,27,uv={{48,0},{35,0},{35,32},-1},f=2},
		{28,30,12,uv={{40,0},{24,0},{24,32},-1},f=2},
		{8,3,2,uv={{120,120},{96,96},{96,120},-1},f=2},
		{6,2,5,uv={{120,120},{96,96},{96,120},-1},f=2},
		{10,4,8,uv={{120,120},{96,96},{96,120},-1},f=2},
		{9,8,6,uv={{120,120},{96,96},{96,120},-1},f=2},
		{16,25,12,uv={{120,120},{96,96},{96,120},-1},f=2},
		{30,16,12,uv={{72,96},{48,128},{72,128},-1},f=2},
		{17,21,18,uv={{96,120},{120,96},{96,96},-1},f=2},
		{1,20,17,uv={{96,120},{120,96},{96,96},-1},f=2},
		{22,21,20,uv={{120,120},{96,96},{96,120},-1},f=2},
		{19,22,20,uv={{96,120},{120,96},{96,96},-1},f=2},
		{14,30,24,uv={{120,120},{96,96},{96,120},-1},f=2},
		{8,4,3,uv={{120,120},{120,96},{96,96},-1},f=2},
		{6,8,2,uv={{120,120},{120,96},{96,96},-1},f=2},
		{10,7,4,uv={{120,120},{120,96},{96,96},-1},f=2},
		{9,10,8,uv={{120,120},{120,96},{96,96},-1},f=2},
		{16,15,25,uv={{120,120},{120,96},{96,96},-1},f=2},
		{30,13,16,uv={{72,96},{48,96},{48,128},-1},f=2},
		{17,20,21,uv={{96,120},{120,120},{120,96},-1},f=2},
		{1,19,20,uv={{96,120},{120,120},{120,96},-1},f=2},
		{22,11,21,uv={{120,120},{120,96},{96,96},-1},f=2},
		{19,23,22,uv={{96,120},{120,120},{120,96},-1},f=2},
		{14,13,30,uv={{120,120},{120,96},{96,96},-1},f=2},
		{16,14,15,uv={{72,128},{48,96},{48,128},-1},f=2},
		{14,25,15,uv={{72,96},{48,128},{72,128},-1},f=2},
		{30,25,12,uv={{96,96},{72,128},{96,128},-1},f=3},
		{16,13,14,uv={{72,128},{72,96},{48,96},-1},f=2},
		{14,24,25,uv={{72,96},{48,96},{48,128},-1},f=2},
		{30,24,25,uv={{96,96},{72,96},{72,128},-1},f=3},
	},
	coll={
		{-96,0  ,-96,96,0  ,96},
		{-96,128,-96,96,128,96},
		--
		{-96,0  ,-96 ,-96,128, 96 },
		{ 96,0  ,-96 , 96,128, 96 },
		{-96,0  ,-96 ,-48,128,-96 },
		{ 48,0  ,-96 , 96,128,-96 },
		{-48,0  ,-192, 48,0  ,-96 },
		{-48,128,-192, 48,128,-96 },
		{-48,0  ,-192, 48,128,-192},
		{-48,0  ,-192,-48,128,-96 },
		{ 48,0  ,-192, 48,128,-96 }
	}
	},
	{ --display -X (21)
		v={
			 {0,60, 68},
			 {0,100,68},
			 {5,60, 68},
			 {5,100,68},
			 {0,60, 28},
			 {0,100,28},
			 {5,60, 28},
			 {5,100,28},
		},
		f={
			 {2,3,1,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {4,7,3,uv={{45,232},{32,245},{45,245},-1},f=2},
			 {8,5,7,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {7,1,3,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {4,6,8,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {2,4,3,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {4,8,7,uv={{45,232},{32,232},{32,245},-1},f=2},
			 {8,6,5,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {7,5,1,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {4,2,6,uv={{45,246},{45,245},{32,245},-1},f=2},
		},
		coll={}
	},
	{ --display +X (22)
		v={
			 {96,60, 28},
			 {96,100,28},
			 {91,60, 28},
			 {91,100,28},
			 {96,60, 68},
			 {96,100,68},
			 {91,60, 68},
			 {91,100,68},
		},
		f={
			 {2,3,1,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {4,7,3,uv={{45,232},{32,245},{45,245},-1},f=2},
			 {8,5,7,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {7,1,3,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {4,6,8,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {2,4,3,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {4,8,7,uv={{45,232},{32,232},{32,245},-1},f=2},
			 {8,6,5,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {7,5,1,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {4,2,6,uv={{45,246},{45,245},{32,245},-1},f=2},
		},
		coll={}
	},
	{ --display -Z (23)
		v={
			 {68,60, 96},
			 {68,100,96},
			 {68,60, 91},
			 {68,100,91},
			 {28,60, 96},
			 {28,100,96},
			 {28,60, 91},
			 {28,100,91},
		},
		f={
			 {2,3,1,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {4,7,3,uv={{45,232},{32,245},{45,245},-1},f=2},
			 {8,5,7,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {7,1,3,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {4,6,8,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {2,4,3,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {4,8,7,uv={{45,232},{32,232},{32,245},-1},f=2},
			 {8,6,5,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {7,5,1,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {4,2,6,uv={{45,246},{45,245},{32,245},-1},f=2},
		},
		coll={}
	},
	{ --display +Z (24)
		v={
			 {28,60, 0},
			 {28,100,0},
			 {28,60, 5},
			 {28,100,5},
			 {68,60, 0},
			 {68,100,0},
			 {68,60, 5},
			 {68,100,5},
		},
		f={
			 {2,3,1,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {4,7,3,uv={{45,232},{32,245},{45,245},-1},f=2},
			 {8,5,7,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {7,1,3,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {4,6,8,uv={{45,246},{32,245},{32,246},-1},f=2},
			 {2,4,3,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {4,8,7,uv={{45,232},{32,232},{32,245},-1},f=2},
			 {8,6,5,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {7,5,1,uv={{45,246},{45,245},{32,245},-1},f=2},
			 {4,2,6,uv={{45,246},{45,245},{32,245},-1},f=2},
		},
		coll={}
	},
}

local s = { --sounds
	t1=0,
	n={0,0,0} --The exact position of the current track
}

local world_size={12,7,12}
world_size[4]=world_size[2]*world_size[3]
world_size[5]=world_size[1]*world_size[2]*world_size[3]
--world
local draw={
	objects={
		c={}, --cubes
		cd={}, --cube dispensers
		lb={}, --light bridges
		b={}, --buttons
		t={}, --turrets
		fb={}, --floor button
		l={}, --lifts
		d={}, --displays
	},
	world={v={},f={},sp={}}, --main world
	map={},
	pr={}, --particles
	pr_g={}, --particle generator (for a light bridge)
	lg={}--light bridge generators
}

--funcions
local addwall, addobj, respal, updpal, darkpal
local menu
--objects data
local objects_data = {
	names={
		"cube",
		"cube dispenser",
		"button",
		"floor button",
		"turret",
		"display",
		"light bridge gerenator",
		"lift"
	},
	types={
		{1,2},
		{3},
		{8,9,10,11},
		{16},
		{12,13,14,15},
		{21,22,23,24},
		nil, --special cases
		nil
	},
	m_step={ -- magnet step multiplier (the minimum lenght of 1 step)
		{24,24 ,24},
		{24,32 ,24},
		{24,128,24},
		{48,128,48},
		{48,128,48},
		{96,128,96},
		{96,128,96}
	}
}

for i = 1, 6 do
	for i2 = 1, #objects_data.types[i] do
		local type = objects_data.types[i][i2]
		for i3 = 1, #model[type].f do
			model[type].f[i3].o = {type = type, tab = i}
		end
	end
end

--time
local t1=0 --The start time of the frame drawing
local t2=0 --The time for drawing the current frame
local t=0 -- Global timer (+1 for each code call)
local stt=0 --The timer of the start of the game
--mouse
local clp1,clp2
local mx, my, cl1, cl2, whl
local cid
local ins --is the cursor in the scene
--sprite editor
local function setpix(sx,sy,color)
	local id=sx//8+sy//8*16
	local adr=sx%8+sy%8*8
	poke4(0x8000+id*64+adr,color)
end

local function getpix(sx,sy)
	local id=sx//8+sy//8*16
	local adr=sx%8+sy%8*8
	return peek4(0x8000+id*64+adr)
end

--maps
local maps={}

--
local function sfx_(...)
	sfx(...)
end
local function addp(x,y,z,vx,vy,vz,lifetime,color) --add particle
	draw.pr[#draw.pr+1]={x=x,y=y,z=z,vx=vx,vy=vy,vz=vz,lt=lifetime,t=0,c=color}
end

--Texture cache
local b_f={} --Texture for the blue field
local p_t={{},{}} --portal texture
for y0=0,31 do
	b_f[y0]={}
	p_t[1][y0]={} --blue portal
	p_t[2][y0]={} --orange portal
	local c=false
	for x0=0,23 do
		local color1=getpix(x0+24,y0+32)
		local color2=getpix((x0+23)%24+24,y0+32)

		if color1~=15 then b_f[y0][3]=color1 c=true end
		if color1~=color2 then
			if color1==15 then b_f[y0][1]=x0 else b_f[y0][2]=x0 end
		end
		p_t[1][y0][x0]=getpix(96+x0,0 +y0)
		p_t[2][y0][x0]=getpix(0 +x0,32+y0)
	end

	b_f[y0].d=c
end

--collision
local function coll(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) --collision of two cubes
	return (x1 < x4 and x2 > x3 and y1 < y4 and y2 > y3 and z1 < z4 and z2 > z3)
end

local function min_abs(a, b)
	if abs(a) < abs(b) then return a else return b end
end

local function max_abs(a, b)
	if abs(a) > abs(b) then return a else return b end
end

local function coll_shift(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, axis)
	if not coll(x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) then
		return 0
	end

	if axis == 1 then
		return min_abs(x3 - x2, x4 - x1)
	elseif axis == 2 then
		return min_abs(y3 - y2, y4 - y1)
	elseif axis == 3 then
		return min_abs(z3 - z2, z4 - z1)
	end
end

local function raycast_legacy(x1,y1,z1, x2,y2,z2, hitwalls,hitfloors, precise) -- walk along a segment, checking whether it collides with the walls
	-- convert to tile space
	x1, y1, z1, x2, y2, z2 = x1 / 96, y1 / 128, z1 / 96, x2 / 96, y2 / 128, z2 / 96
	-- DDA, loosely based on https://lodev.org/cgtutor/raycasting.html
	-- segment direction
	local dirx, diry, dirz = x2-x1, y2-y1, z2-z1
	-- length of one step along axes (only relative)
	-- n/0 = inf, which is fine for this algorithm
	local lx, ly, lz = abs(1 / dirx), abs(1 / diry), abs(1 / dirz)
	-- full tile step, matching direction with the segment
	local sx, sy, sz
	-- offset, for handling negative facing
	local ox, oy, oz
	-- current tile (offset if facing positive)
	local x, y, z = F(x1), F(y1), F(z1)
	-- distance to next tile in each axis
	local tx, ty, tz = (x1 - x) * lx, (y1 - y) * ly, (z1 - z) * lz
	if dirx < 0 then
		sx, ox = -1, 1
	else
		sx, ox = 1, 0
		tx = lx - tx
	end
	if diry < 0 then
		sy, oy = -1, 1
	else
		sy, oy = 1, 0
		ty = ly - ty
	end
	if dirz < 0 then
		sz, oz = -1, 1
	else
		sz, oz = 1, 0
		tz = lz - tz
	end

	if x < 0 or x > world_size[1] - 1 or
		y < 0 or y > world_size[2] - 1 or
		z < 0 or z > world_size[3] - 1 then
		return
	end

	while true do
		if tx < ty and tx < tz then
			x, tx = x + sx, tx + lx
			if (x + ox) * sx > x2 * sx or (x + ox) < 0 or (x + ox) > world_size[1] - 1 then
				return
			elseif hitwalls[draw.map[1][x + ox][y][z][2]] then
				if precise then
					local ratio = (x + ox - x1) / dirx
					return (x + ox) * 96, (y1 + diry * ratio) * 128, (z1 + dirz * ratio) * 96, 1
				else
					return x + ox, y, z, 1
				end
			elseif x < 0 then
				return
			end
		elseif ty < tz then
			y, ty = y + sy, ty + ly
			if (y + oy) * sy > y2 * sy or (y + oy) < 0 or (y + oy) > world_size[2] - 1 then
				return
			elseif hitfloors[draw.map[2][x][y + oy][z][2]] then
				if precise then
					local ratio = (y + oy - y1) / diry
					return (x1 + dirx * ratio) * 96, (y + oy) * 128, (z1 + dirz * ratio) * 96, 1
				else
					return x, y + oy, z, 2
				end
			elseif y < 0 then
				return
			end
		else
			z, tz = z + sz, tz + lz
			if (z + oz) * sz > z2 * sz or (z + oz) < 0 or (z + oz) > world_size[3] - 1 then
				return
			elseif hitwalls[draw.map[3][x][y][z + oz][2]] then
				if precise then
					local ratio = (z + oz - z1) / dirz
					return (x1 + dirx * ratio) * 96, (y1 + diry * ratio) * 128, (z + oz) * 96, 1
				else
					return x, y, z + oz, 3
				end
			elseif z < 0 then
				return
			end
		end
	end
end

local function get_tile(axis, x, y, z)
	local step = draw.map
	step = step[axis]
	step = step[x]
	if not step then return nil end
	step = step[y]
	if not step then return nil end
	step = step[z]
	return step
end

-- Calculate the difference between a value and the next step in a direction
local function to_next(val, interval, dir)
	-- Round to remove fp error
	local nval = F(val + 0.5)
	local next_pos
	if dir > 0 then
		next_pos = F(nval / interval) * interval + interval
	else
		next_pos = math.ceil(nval / interval) * interval - interval
	end
	return next_pos - val
end

-- Check if a ray hits an object's colliders
local function ray_object(x, y, z, rx, ry, rz, obj)
	local nearest = 1/0
	local colliders = obj.coll or model[obj.type].coll
	for _,collider in ipairs(colliders) do
		local cx1, cy1, cz1 =
			(obj.x + collider[1] - x) / rx, (obj.y + collider[2] - y) / ry, (obj.z + collider[3] - z) / rz
		local cx2, cy2, cz2 =
			(obj.x + collider[4] - x) / rx, (obj.y + collider[5] - y) / ry, (obj.z + collider[6] - z) / rz
		if cx1 > cx2 then cx1, cx2 = cx2, cx1 end
		if cy1 > cy2 then cy1, cy2 = cy2, cy1 end
		if cz1 > cz2 then cz1, cz2 = cz2, cz1 end
		local near, far = max(cx1, cy1, cz1), min(cx2, cy2, cz2)
		if near > 0 and near <= far and near < nearest then nearest = near end
	end
	if nearest ~= 1/0 then
		return nearest
	end
end

-- Check if a ray hits a box
local function ray_aabb(x, y, z, rx, ry, rz, cx1, cy1, cz1, cx2, cy2, cz2)
	cx1, cy1, cz1 = (cx1 - x) / rx, (cy1 - y) / ry, (cz1 - z) / rz
	cx2, cy2, cz2 = (cx2 - x) / rx, (cy2 - y) / ry, (cz2 - z) / rz
	if cx1 > cx2 then cx1, cx2 = cx2, cx1 end
	if cy1 > cy2 then cy1, cy2 = cy2, cy1 end
	if cz1 > cz2 then cz1, cz2 = cz2, cz1 end
	local near, far = max(cx1, cy1, cz1), min(cx2, cy2, cz2)
	if near > 0 and near <= far then
		return near
	end
end

local function raycast(x, y, z, rx, ry, rz, len, params)
	-- allow passing an end point instead
	if not len then
		rx, ry, rz = rx - x, ry - y, rz - z
	end

	-- normalised ray vector
	local dist = math.sqrt(rx^2 + ry^2 + rz^2)
	local nx, ny, nz = rx / dist, ry / dist, rz / dist
	local tilehit

	-- allow passing an end point instead
	len = len or dist

	-- if we are starting out of bounds, adjust start
	if x < 0 or x > world_size[1] * 96 or y < 0 or y > world_size[2] * 128 or z < 0 or z > world_size[3] * 96 then
		local hit_len = ray_aabb(
			x, y, z, rx, ry, rz,
			-1, -1, -1,
			world_size[1] * 96 - 95, world_size[2] * 128 - 95, world_size[3] * 96 - 95
		)
		if hit_len and hit_len * dist < len then
			len = len - hit_len * dist
			x, y, z = x + rx * hit_len, y + ry * hit_len, z + rz * hit_len
		end
	end

	-- current scan coordinates and remaining length
	local cx, cy, cz = x, y, z
	local remaining_len = len

	while true do
		-- calculate the amount each component should step
		local sx, sy, sz = to_next(cx, 96, rx), to_next(cy, 128, ry), to_next(cz, 96, rz)
		-- calculate the distance travelled by each component step
		local lx, ly, lz = sx / nx, sy / ny, sz / nz
		-- select the smallest as the next step
		local lookup, axis
		if lx < ly and lx < lz then
			cx, cy, cz = cx + sx, cy + lx * ny, cz + lx * nz
			remaining_len = remaining_len - lx
			lookup, axis = params.walls, 1
		elseif ly < lz then
			cx, cy, cz = cx + ly * nx, cy + sy, cz + ly * nz
			remaining_len = remaining_len - ly
			lookup, axis = params.floors, 2
		else
			cx, cy, cz = cx + lz * nx, cy + lz * ny, cz + sz
			remaining_len = remaining_len - lz
			lookup, axis = params.walls, 3
		end
		-- stop if we've travelled far enough
		if remaining_len < 0 then break end
		-- fetch and check the current tile
		local tx, ty, tz = (cx+0.01)//96, (cy+0.01)//128, (cz+0.01)//96
		tile = get_tile(axis, tx, ty, tz)
		if not tile then break end
		if lookup[tile[2]] then
			-- we hit a tile, break out of the loop and start testing objects
			tilehit = {
				x=cx, y=cy, z=cz, len=len - remaining_len,
				tx=tx, ty=ty, tz=tz,
				axis=axis, tile=tile
			}
			break
		end
	end
	-- scan through all objects, find nearest intersection
	local objhit
	for _,ty in ipairs(params.objs) do
		for _,obj in ipairs(draw.objects[ty]) do
			local hit_len = ray_object(x, y, z, rx, ry, rz, obj)
			if hit_len and hit_len * dist < len then
				if not objhit or objhit.len > hit_len * dist then
					objhit = {
						x=x+rx*hit_len, y=y+ry*hit_len, z=z+rz*hit_len, len=hit_len*dist,
						obj=obj,
					}
				end
			end
		end
	end
	-- same for player
	if params.player then
		hit_len = ray_object(x, y, z, rx, ry, rz, {
			x=plr.x, y=plr.y, z=plr.z,
			coll={{-16,-64,-16,16,16,16}},
		})
		if hit_len and hit_len * dist < len then
			if not objhit or objhit.len > hit_len * dist then
				objhit = {
					x=x+rx*hit_len, y=y+ry*hit_len, z=z+rz*hit_len, len=hit_len*dist,
					player=true,
				}
			end
		end
	end
	-- return the shortest found intersection
	if not objhit or (tilehit and tilehit.len < objhit.len) then
		return tilehit
	else
		return objhit
	end
end

function unitic.update()
	--writing all polygons in unitic.poly
	unitic.poly = { v = {}, f = {}, sp = {} }
	unitic.obj  = {}
	unitic.p    = {}
	--world--
	for ind = 1, #draw.world.v do
		unitic.poly.v[ind] = {
			draw.world.v[ind][1],
			draw.world.v[ind][2],
			draw.world.v[ind][3]
		}
	end
	--faces
	for ind=1,#draw.world.f do
		unitic.poly.f[ind]={
			draw.world.f[ind][1],
			draw.world.f[ind][2],
			draw.world.f[ind][3],
			f=draw.world.f[ind].f,
			uv=draw.world.f[ind].uv,
			w=draw.world.f[ind].w
		} end
	--objects (1)--
	local i2=0
	
	local highlighting = nil
	local obj_index = {
		"c",
		"cd",
		"b",
		"fb",
		"t",
		"d",
		"lb",
		"l",
	}

	for ind = 1,#obj_index do
		for i = 1,#draw.objects[obj_index[ind]] do
			i2 = i2 + 1
			if menu.open and menu.type==2 and menu.o.tab == ind and menu.o.sel[menu.o.tab]==i then highlighting = i2 end
			unitic.obj[i2]=draw.objects[obj_index[ind]][i]
		end
	end
	--objects (2)--
	local i2=#unitic.poly.f

	for ind1 = 1, #unitic.obj do
		if unitic.obj[ind1].draw then
			local vt=#unitic.poly.v
			for ind2=1,#unitic.obj[ind1].model.v do
				local px=unitic.obj[ind1].model.v[ind2][1]+unitic.obj[ind1].x
				local py=unitic.obj[ind1].model.v[ind2][2]+unitic.obj[ind1].y
				local pz=unitic.obj[ind1].model.v[ind2][3]+unitic.obj[ind1].z
				unitic.poly.v[#unitic.poly.v+1]={px,py,pz}
			end
			for ind2=1,#unitic.obj[ind1].model.f do
				i2=i2+1
				unitic.poly.f[i2]={
					unitic.obj[ind1].model.f[ind2][1]+vt,
					unitic.obj[ind1].model.f[ind2][2]+vt,
					unitic.obj[ind1].model.f[ind2][3]+vt,
					f=unitic.obj[ind1].model.f[ind2].f,
					o=unitic.obj[ind1].model.f[ind2].o,
					uv={
						x={unitic.obj[ind1].model.f[ind2].uv[1][1],unitic.obj[ind1].model.f[ind2].uv[2][1],unitic.obj[ind1].model.f[ind2].uv[3][1]},
						y={unitic.obj[ind1].model.f[ind2].uv[1][2],unitic.obj[ind1].model.f[ind2].uv[2][2],unitic.obj[ind1].model.f[ind2].uv[3][2]}
					},
					hl = (highlighting == ind1)
				}
			end
		end
	end
	--rotate all polygons
	local txsin = math.sin(cam.tx)
	local txcos = math.cos(cam.tx)
	local tysin = math.sin(-cam.ty)
	local tycos = math.cos(-cam.ty)

	for ind = 1, #unitic.poly.v do
		if unitic.poly.v[4]~=false then -- true or nil
		local a1 = unitic.poly.v[ind][1] - cam.x
		local b1 = unitic.poly.v[ind][2] - cam.y
		local c1 = unitic.poly.v[ind][3] - cam.z

		local c2 = c1 * tycos - a1 * tysin

		local a3 = c1 * tysin + a1 * tycos
		local b3 = b1 * txcos - c2 * txsin
		local c3 = b1 * txsin + c2 * txcos
		local c4 = c3
		if c4>-0.001 then c4=-0.001 end
		local z0 = unitic.fov / c4 --this saves one division (very important optimization)

		local x0 = a3 * z0 + 120
		local y0 = b3 * z0 + 68

		unitic.poly.v[ind][1]=x0
		unitic.poly.v[ind][2]=y0
		unitic.poly.v[ind][3]=-c4
		unitic.poly.v[ind][4]=c3>0
		end
	end

	--particles
	for ind = 1, #draw.pr do
		local a1 = draw.pr[ind].x - cam.x
		local b1 = draw.pr[ind].y - cam.y
		local c1 = draw.pr[ind].z - cam.z

		local c2 = c1 * tycos - a1 * tysin

		local x0 = c1 * tysin + a1 * tycos
		local y0 = b1 * txcos - c2 * txsin
		local z0 = b1 * txsin + c2 * txcos

		local dist=math.sqrt(x0^2+y0^2+z0^2)

		local draw_p=false
		if z0<0 then draw_p=true end

		if z0>-0.001 then z0=-0.001 end

		local z1 = unitic.fov / z0 --this saves one division (very important optimization)

		local x1 = x0 * z1 + 120
		local y1 = y0 * z1 + 68

		unitic.p[ind]={x1, y1, -z0, draw_p, draw.pr[ind].c, dist}
	end
end

function unitic.update_pr() --update particles
	local i=0 if #draw.pr~=0 then
	repeat
		i=i+1

		draw.pr[i].x = draw.pr[i].x+draw.pr[i].vx
		draw.pr[i].y = draw.pr[i].y+draw.pr[i].vy
		draw.pr[i].z = draw.pr[i].z+draw.pr[i].vz

		draw.pr[i].t = draw.pr[i].t+1

		if draw.pr[i].t==draw.pr[i].lt then table.remove(draw.pr,i) i=i-1 end
	until i>=#draw.pr end
end

function unitic.draw()
	for i = 1, #unitic.poly.f do
		local poly = unitic.poly.f[i]

		local uv = poly.uv
		
		local p2d = {
			x = { unitic.poly.v[poly[1]][1], unitic.poly.v[poly[2]][1], unitic.poly.v[poly[3]][1] },
			y = { unitic.poly.v[poly[1]][2], unitic.poly.v[poly[2]][2], unitic.poly.v[poly[3]][2] }
		}

		--we discard those polygons that will not be visible
		if poly.f~=0
		and not (unitic.poly.v[poly[1]][4] and unitic.poly.v[poly[2]][4] and unitic.poly.v[poly[3]][4])
		and not (p2d.x[1]<0 and p2d.x[2]<0 and p2d.x[3]<0)
		and not (p2d.y[1]<0 and p2d.y[2]<0 and p2d.y[3]<0)
		and not (p2d.x[1]>239 and p2d.x[2]>239 and p2d.x[3]>239)
		and not (p2d.y[1]>135 and p2d.y[2]>135 and p2d.y[3]>135)
		then

			local tri_face
			if  poly.f~=3 then
				tri_face = (p2d.x[2] - p2d.x[1]) * (p2d.y[3] - p2d.y[1]) - (p2d.x[3] - p2d.x[1]) * (p2d.y[2] - p2d.y[1]) < 0
			end

			if not (tri_face and poly.f==1)
			and not (not tri_face and poly.f==2)
			then
				ttri(
					p2d.x[1], p2d.y[1],
					p2d.x[2], p2d.y[2],
					p2d.x[3], p2d.y[3],
					uv.x[1], uv.y[1],
					uv.x[2], uv.y[2],
					uv.x[3], uv.y[3], 0, 15,
					unitic.poly.v[poly[1]][3],
					unitic.poly.v[poly[2]][3],
					unitic.poly.v[poly[3]][3])
			elseif poly.w then
					if poly.w[7]==1 then
						if poly.w[2]==2 then ttri(p2d.x[1],p2d.y[1],p2d.x[2],p2d.y[2],p2d.x[3],p2d.y[3],0,200,24,200,0,176,0,15,unitic.poly.v[poly[1]][3],unitic.poly.v[poly[2]][3],unitic.poly.v[poly[3]][3])
						else ttri(p2d.x[1],p2d.y[1],p2d.x[2],p2d.y[2],p2d.x[3],p2d.y[3],120,32,96,32,120,0,0,15,unitic.poly.v[poly[1]][3],unitic.poly.v[poly[2]][3],unitic.poly.v[poly[3]][3])
						end
					else
						if poly.w[2]==2 then ttri(p2d.x[1],p2d.y[1],p2d.x[2],p2d.y[2],p2d.x[3],p2d.y[3],24,200,24,176,0,176,0,15,unitic.poly.v[poly[1]][3],unitic.poly.v[poly[2]][3],unitic.poly.v[poly[3]][3])
						else ttri(p2d.x[1],p2d.y[1],p2d.x[2],p2d.y[2],p2d.x[3],p2d.y[3],96,32,96,0,120,0,0, 15,unitic.poly.v[poly[1]][3],unitic.poly.v[poly[2]][3],unitic.poly.v[poly[3]][3])
						end
					end
			end
			if menu.open then
				if menu.type==1 and poly.w then
					if poly.w[6] == menu.w.m_sel then
						line(p2d.x[1],p2d.y[1],p2d.x[2],p2d.y[2],13)
						if i&1 == 0 then
							line(p2d.x[2],p2d.y[2],p2d.x[3],p2d.y[3],13)
						else
							line(p2d.x[3],p2d.y[3],p2d.x[1],p2d.y[1],13)
						end
					elseif poly.w[6] == menu.w.sel then
						line(p2d.x[1],p2d.y[1],p2d.x[2],p2d.y[2],7)
						if i&1 == 0 then
							line(p2d.x[2],p2d.y[2],p2d.x[3],p2d.y[3],7)
						else
							line(p2d.x[3],p2d.y[3],p2d.x[1],p2d.y[1],7)
						end
					end
				elseif menu.type==2 and poly.o then
					if poly.hl then
						line(p2d.x[1],p2d.y[1],p2d.x[2],p2d.y[2],7)
						line(p2d.x[2],p2d.y[2],p2d.x[3],p2d.y[3],7)
						line(p2d.x[3],p2d.y[3],p2d.x[1],p2d.y[1],7)

					-- I have no idea what I'm doing
					-- I'm just got tired

					-- elseif poly.o.tab == menu.o.m_tab and poly.o.type == menu.o.m_sel then
					-- 	line(p2d.x[1],p2d.y[1],p2d.x[2],p2d.y[2],13)
					-- 	line(p2d.x[2],p2d.y[2],p2d.x[3],p2d.y[3],13)
					-- 	line(p2d.x[3],p2d.y[3],p2d.x[1],p2d.y[1],13)

					end
				end
			end
		end
	end

	if #unitic.p~=0 then
		for i = 1, #unitic.p do
			if unitic.p[i][4] then
				local p2d = {x=unitic.p[i][1],y=unitic.p[i][2]}

				local color = unitic.p[i][5]
				local color1= color % 4
				local color2= color //4
				local size = 1/unitic.p[i][6]*2.4*unitic.fov

				if color == 0 then size = 1 end

				local z0 = unitic.p[i][3]

				ttri(
					p2d.x-size,p2d.y-size,
					p2d.x-size,p2d.y+size,
					p2d.x+size,p2d.y+size,
					24 + color1*2,248 + color2*2,
					24 + color1*2,249 + color2*2,
					25 + color1*2,248 + color2*2,
					0,-1,z0,z0,z0)
				ttri(
					p2d.x+size,p2d.y-size,
					p2d.x-size,p2d.y-size,
					p2d.x+size,p2d.y+size,
					24 + color1*2,248 + color2*2,
					24 + color1*2,249 + color2*2,
					25 + color1*2,248 + color2*2,
					0,-1,z0,z0,z0)
			end
		end
	end
end

local wall_coll={[1]=true,[2]=true,[3]=true,[4]=true,[8]=true,[9]=true,[10]=true,[13]=true,[14]=true,[16]=true,[17]=true,[18]=true}

function unitic.player_physics()
	--control
	plr.lx, plr.ly, plr.lz = plr.x, plr.y, plr.z

	plr.speed = 4

	if key(64) and key(23) then
		plr.speed = 8
	end

	if plr.noclip then plr.speed = 12 end

	local vec = {x=0, y=0, z=0} --vector

	if key(23) then vec.z = vec.z - 1 end -- W
	if key(19) then vec.z = vec.z + 1 end -- S
	if key(1 ) then vec.x = vec.x + 1 end -- A
	if key(4 ) then vec.x = vec.x - 1 end -- D
	if plr.noclip then
		if key(48) then vec.y = vec.y + 1 end -- space
		if key(63) then vec.y = vec.y - 1 end -- CTRL
	end

	local vec_len = math.sqrt(vec.x^2 + vec.y^2 + vec.z^2)
	if vec_len~=0 then --normalization
		vec.x = vec.x / vec_len * plr.speed
		vec.y = vec.y / vec_len * plr.speed
		vec.z = vec.z / vec_len * plr.speed
	end
	--rotation
	
	local vx =  vec.x * math.cos(plr.ty) + vec.z * math.sin(plr.ty)
	local vz	= -vec.x * math.sin(plr.ty) + vec.z * math.cos(plr.ty)

	vec.x, vec.z = vx,vz

	--jump
	if plr.on_ground then
		plr.vy = -1
		if keyp(48) then plr.vy = 8 end
	end

	plr.vy = max(plr.vy - 0.5, -20) --gravity

	--horizontal velociy
	if plr.on_ground then
		plr.vx = max_abs(plr.vx * 0.8, vec.x)
		plr.vz = max_abs(plr.vz * 0.8, vec.z)
	else
		if abs(plr.vx) > 9 or abs(plr.vz) > 9 then
			if vec.x~=0 or vec.z~=0 then
				plr.vx = plr.vx * 0.95 + vec.x * 0.05
				plr.vz = plr.vz * 0.95 + vec.z * 0.05
			end
		else
			plr.vx = max_abs(plr.vx * 0.9, vec.x)
			plr.vz = max_abs(plr.vz * 0.9, vec.z)
		end
	end
	--noclip
	if plr.noclip then
		plr.vx = vec.x
		plr.vy = vec.y
		plr.vz = vec.z
	end

	if keyp(7) then plr.vx = 20 end


	plr.vx = max(min(plr.vx, 20), -20)
	plr.vy = max(min(plr.vy, 20), -20)
	plr.vz = max(min(plr.vz, 20), -20)

	plr.x = plr.x + plr.vx
	plr.y = plr.y + plr.vy
	plr.z = plr.z + plr.vz
	
	--cheats
	if keyp(57) or keyp(22) then plr.y = plr.y + 2 plr.noclip = not plr.noclip end

	--zoom
	if key(65) then
		unitic.fov=min(unitic.fov*1.2,800)
	else
		unitic.fov=max(unitic.fov/1.2,80)
	end
	
	--collision
	local colx = false
	local coly = false
	local colz = false

	local function plr_collide(x1,y1,z1,x2,y2,z2)
		local ti=false
		if not coll(plr.lx - 16, plr.ly - 64, plr.lz - 16, plr.lx + 16, plr.ly + 16, plr.lz + 16, x1,y1,z1, x2,y2,z2) then
			if coll(plr.x - 16, plr.ly - 64, plr.lz - 16, plr.x + 16, plr.ly + 16, plr.lz + 16, x1,y1,z1, x2,y2,z2) then ti = true colx=true end
			if coll(plr.lx - 16, plr.y - 64, plr.lz - 16, plr.lx + 16, plr.y + 16, plr.lz + 16, x1,y1,z1, x2,y2,z2) then ti = true coly=true end
			if coll(plr.lx - 16, plr.ly - 64, plr.z - 16, plr.lx + 16, plr.ly + 16, plr.z + 16, x1,y1,z1, x2,y2,z2) then ti = true colz=true end
			if not ti and coll(plr.x - 16, plr.y - 64, plr.z - 16, plr.x + 16, plr.y + 16, plr.z + 16, x1,y1,z1, x2,y2,z2) then
				if y1~=y2 and z1~=z2 then colx=true end
				if x1~=x2 and z1~=z2 then coly=true end
				if x1~=x2 and y1~=y2 then colz=true end
			end
		end
	end

	local function obj_collide(id,x,y,z)
		if #model[id].coll==0 then return end
		for i=1,#model[id].coll do
			local col1=model[id].coll[i]
			plr_collide(x+col1[1],y+col1[2],z+col1[3], x+col1[4],y+col1[5],z+col1[6])
		end
	end

	local x1=max((plr.x-17)//96,0)
	local y1=max((plr.y-65)//128,0)
	local z1=max((plr.z-17)//96,0)

	local x2=min((plr.x+16)//96,world_size[1]-1)
	local y2=min((plr.y+16)//128,world_size[2]-1)
	local z2=min((plr.z+16)//96,world_size[3]-1)

	for x0 = x1,x2 do for y0 = y1,y2 do for z0 = z1,z2 do
		if wall_coll[draw.map[1][x0][y0][z0][2]] then
			plr_collide(x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 94)
		elseif draw.map[1][x0][y0][z0][2]==5 or draw.map[1][x0][y0][z0][2]==6 then
			if not draw.p[1] or not draw.p[2] then
				plr_collide(x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 94)
			else
				if coll(plr.x - 16, plr.ly - 64, plr.lz - 16, plr.x + 16, plr.ly + 16, plr.lz + 16, x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 2)
				or coll(plr.x - 16, plr.ly - 64, plr.lz - 16, plr.x + 16, plr.ly + 16, plr.lz + 16, x0 * 96, y0 * 128 + 2, z0 * 96 + 94, x0 * 96, y0 * 128 + 126, z0 * 96 + 94)
				or coll(plr.x - 16, plr.ly - 64, plr.lz - 16, plr.x + 16, plr.ly + 16, plr.lz + 16, x0 * 96, y0 * 128 + 126, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 94) then colx = true end

				if coll(plr.lx - 16, plr.y - 64, plr.lz - 16, plr.lx + 16, plr.y + 16, plr.lz + 16, x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 2)
				or coll(plr.lx - 16, plr.y - 64, plr.lz - 16, plr.lx + 16, plr.y + 16, plr.lz + 16, x0 * 96, y0 * 128 + 2, z0 * 96 + 94, x0 * 96, y0 * 128 + 126, z0 * 96 + 94)
				or coll(plr.lx - 16, plr.y - 64, plr.lz - 16, plr.lx + 16, plr.y + 16, plr.lz + 16, x0 * 96, y0 * 128 + 126, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 94) then coly = true end

				if coll(plr.lx - 16, plr.ly - 64, plr.z - 16, plr.lx + 16, plr.ly + 16, plr.z + 16, x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 2)
				or coll(plr.lx - 16, plr.ly - 64, plr.z - 16, plr.lx + 16, plr.ly + 16, plr.z + 16, x0 * 96, y0 * 128 + 2, z0 * 96 + 94, x0 * 96, y0 * 128 + 126, z0 * 96 + 94)
				or coll(plr.lx - 16, plr.ly - 64, plr.z - 16, plr.lx + 16, plr.ly + 16, plr.z + 16, x0 * 96, y0 * 128 + 126, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 94) then colz = true end
			end
		elseif draw.map[1][x0][y0][z0][2]==11 then
			plr_collide(x0 * 96, y0 * 128 + 2, z0 * 96 + 62, x0 * 96, y0 * 128 + 126, z0 * 96 + 94)
		elseif draw.map[1][x0][y0][z0][2]==12 then
			plr_collide(x0 * 96, yM 0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 34)
		elseif draw.map[1][x0][y0][z0][2]==7 then
			if coll(plr.lx - 16, plr.ly - 64, plr.lz - 16, plr.lx + 16, plr.ly + 16, plr.lz + 16, x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 94) then plr.cd2=10 end
		elseif draw.map[1][x0][y0][z0][2]==15 then
			if coll(plr.lx - 16, plr.ly - 64, plr.lz - 16, plr.lx + 16, plr.ly + 16, plr.lz + 16, x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 94) then plr.hp=0 sfx_(2,"C-3",-1,1) end
		end

		if draw.map[2][x0][y0][z0][2] > 0 and draw.map[2][x0][y0][z0][2]~=5 and draw.map[2][x0][y0][z0][2]~=8 and draw.map[2][x0][y0][z0][2]~=9 then
			plr_collide(x0 * 96 + 2, y0 * 128, z0 * 96 + 2, x0 * 96 + 94, y0 * 128, z0 * 96 + 94)
		elseif draw.map[2][x0][y0][z0][2]==5 then
			if coll(plr.lx - 16, plr.ly - 64, plr.lz - 16, plr.lx + 16, plr.ly + 16, plr.lz + 16, x0 * 96 + 2, y0 * 128, z0 * 96 + 2, x0 * 96 + 94, y0 * 128, z0 * 96 + 94) then plr.hp=0 sfx_(2,"C-3",-1,1) end
		elseif draw.map[2][x0][y0][z0][2]==8 or draw.map[2][x0][y0][z0][2]==9 then
			if coll(plr.lx - 16, plr.ly - 64, plr.lz - 16, plr.lx + 16, plr.ly + 16, plr.lz + 16, x0 * 96 + 2, y0 * 128, z0 * 96 + 2, x0 * 96 + 94, y0 * 128, z0 * 96 + 94) then plr.vy=12 sfx_(0,"C-6",-1,1) end
		end

		if wall_coll[draw.map[3][x0][y0][z0][2]] then
			plr_collide(x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96)
		elseif draw.map[3][x0][y0][z0][2]==5 or draw.map[3][x0][y0][z0][2]==6 then
			if not draw.p[1] or not draw.p[2] then
				plr_collide(x0 * 96, y0 * 128, z0 * 96, x0 * 96 + 96, y0 * 128 + 128, z0 * 96)
			else
				if coll(plr.x - 16, plr.ly - 64, plr.lz - 16, plr.x + 16, plr.ly + 16, plr.lz + 16, x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 2, y0 * 128 + 126, z0 * 96)
				or coll(plr.x - 16, plr.ly - 64, plr.lz - 16, plr.x + 16, plr.ly + 16, plr.lz + 16, x0 * 96 + 94, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96)
				or coll(plr.x - 16, plr.ly - 64, plr.lz - 16, plr.x + 16, plr.ly + 16, plr.lz + 16, x0 * 96 + 2, y0 * 128 + 126, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96) then colx = true end

				if coll(plr.lx - 16, plr.y - 64, plr.lz - 16, plr.lx + 16, plr.y + 16, plr.lz + 16, x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 2, y0 * 128 + 126, z0 * 96)
				or coll(plr.lx - 16, plr.y - 64, plr.lz - 16, plr.lx + 16, plr.y + 16, plr.lz + 16, x0 * 96 + 94, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96)
				or coll(plr.lx - 16, plr.y - 64, plr.lz - 16, plr.lx + 16, plr.y + 16, plr.lz + 16, x0 * 96 + 2, y0 * 128 + 126, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96) then coly = true end

				if coll(plr.lx - 16, plr.ly - 64, plr.z - 16, plr.lx + 16, plr.ly + 16, plr.z + 16, x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 2, y0 * 128 + 126, z0 * 96)
				or coll(plr.lx - 16, plr.ly - 64, plr.z - 16, plr.lx + 16, plr.ly + 16, plr.z + 16, x0 * 96 + 94, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96)
				or coll(plr.lx - 16, plr.ly - 64, plr.z - 16, plr.lx + 16, plr.ly + 16, plr.z + 16, x0 * 96 + 2, y0 * 128 + 126, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96) then colz = true end
			end
		elseif draw.map[3][x0][y0][z0][2]==7 then
			if coll(plr.lx - 16, plr.ly - 64, plr.lz - 16, plr.lx + 16, plr.ly + 16, plr.lz + 16, x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96) then plr.cd2=10 end
		elseif draw.map[3][x0][y0][z0][2]==11 then
			plr_collide(x0 * 96 + 62, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96)
		elseif draw.map[3][x0][y0][z0][2]==12 then
			plr_collide(x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 34, y0 * 128 + 126, z0 * 96)
		elseif draw.map[3][x0][y0][z0][2]==15 then
			if coll(plr.lx - 16, plr.ly - 64, plr.lz - 16, plr.lx + 16, plr.ly + 16, plr.lz + 16, x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96) then plr.hp=0 sfx_(2,"C-3",-1,1) end
		end
	end end end
	--collision with objects
	for i=1,#draw.objects.c do
		local x0=draw.objects.c[i].x
		local y0=draw.objects.c[i].y
		local z0=draw.objects.c[i].z
		obj_collide(1, x0, y0, z0)
		if draw.objects.c[i].held and coll(plr.lx - 16, plr.ly - 64, plr.lz - 16, plr.lx + 16, plr.ly + 16, plr.lz + 16, x0 - 24, y0 + 24, z0 - 24, x0 + 24, y0 + 24.1, z0 + 24) then draw.objects.c[i].held=false plr.holding=false end
		if draw.objects.c[i].inp then
			local x0=draw.objects.c[i].x1
			local y0=draw.objects.c[i].y1
			local z0=draw.objects.c[i].z1
			obj_collide(1, x0, y0, z0)
		end
	end

	local object_types = {"cd", "lb", "b", "t", "l"}
	for _,type in ipairs(object_types) do
		for _,obj in ipairs(draw.objects[type]) do
			local x0, y0, z0 = obj.x, obj.y, obj.z
			obj_collide(obj.type, x0, y0, z0)
		end
	end

	if not plr.noclip then
		if colx then plr.x = plr.lx end
		if coly then plr.y = plr.ly end
		if colz then plr.z = plr.lz end
	end

	plr.y = max(plr.y, -256)

	plr.on_ground = coly or plr.y==-256
end

function unitic.cube_update() --all physics related to cubes
	-- dispensers
	for i=1,#draw.objects.cd do
		draw.objects.cd[i].t=draw.objects.cd[i].t-1
		if draw.objects.cd[i].t==1 then
			addobj(draw.objects.cd[i].x,draw.objects.cd[i].y,draw.objects.cd[i].z,draw.objects.cd[i].ct,i)
		end
	end
	--cubes
	local i=0
	if #draw.objects.c==0 then return end

	repeat
		i=i+1

		local clx=draw.objects.c[i].x
		local cly=draw.objects.c[i].y
		local clz=draw.objects.c[i].z

		local cx=draw.objects.c[i].x
		local cy=draw.objects.c[i].y
		local cz=draw.objects.c[i].z

		cx=cx + draw.objects.c[i].vx
		cy=cy + draw.objects.c[i].vy
		cz=cz + draw.objects.c[i].vz

		draw.objects.c[i].vx=draw.objects.c[i].vx*0.9
		draw.objects.c[i].vy=draw.objects.c[i].vy-0.5
		draw.objects.c[i].vz=draw.objects.c[i].vz*0.9

		if     draw.objects.c[i].vx<-20 then draw.objects.c[i].vx=-20
		elseif draw.objects.c[i].vx> 20 then draw.objects.c[i].vx= 20 end
		
		if     draw.objects.c[i].vy<-20 then draw.objects.c[i].vy=-20
		elseif draw.objects.c[i].vy> 20 then draw.objects.c[i].vy= 20 end
		
		if     draw.objects.c[i].vz<-20 then draw.objects.c[i].vz=-20
		elseif draw.objects.c[i].vz> 20 then draw.objects.c[i].vz= 20 end


		
		local bf = false --is the cube in the blue field

		local x1=(cx-25)//96
		local y1=(cy-25)//128
		local z1=(cz-25)//96

		if x1<0 then x1 = 0 end
		if y1<0 then y1 = 0 end
		if z1<0 then z1 = 0 end

		local x2=(cx+25)//96
		local y2=(cy+25)//128
		local z2=(cz+25)//96

		if x2>world_size[1]-1 then x2 = world_size[1]-1 end
		if y2>world_size[2]-1 then y2 = world_size[2]-1 end
		if z2>world_size[3]-1 then z2 = world_size[3]-1 end

		local function collide(x3, y3, z3, x4, y4, z4)
			-- try moving the current amount in each axis, partially cancelling if needed
			if not coll(cx - 24, cy - 24, cz - 24, cx + 24, cy + 24, cz + 24, x3, y3, z3, x4, y4, z4) then return end

			local sx = coll_shift(
				cx - 24, cly - 24, clz - 24, cx + 24, cly + 24, clz + 24,
				x3, y3, z3, x4, y4, z4, 1
			)
			if sx ~= 0 then draw.objects.c[i].vx = 0 end
			cx = cx + sx
			local sy = coll_shift(
				clx - 24, cy - 24, clz - 24, clx + 24, cy + 24, clz + 24,
				x3, y3, z3, x4, y4, z4, 2
			)
			if sy ~= 0 then draw.objects.c[i].vy = 0 end
			cy = cy + sy
			local sz = coll_shift(
				clx - 24, cly - 24, cz - 24, clx + 24, cly + 24, cz + 24,
				x3, y3, z3, x4, y4, z4, 3
			)
			if sz ~= 0 then draw.objects.c[i].vz = 0 end
			cz = cz + sz
		end

		local function obj_collide(id,x,y,z)
			if #model[id].coll==0 then return end
			for i=1,#model[id].coll do
				local col1=model[id].coll[i]
				collide(x+col1[1],y+col1[2],z+col1[3], x+col1[4],y+col1[5],z+col1[6])
			end
		end

		for x0 = x1,x2 do for y0 = y1,y2 do for z0 = z1,z2 do
			if wall_coll[draw.map[1][x0][y0][z0][2]] then
				collide(x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 94)
			elseif draw.map[1][x0][y0][z0][2]==5 or draw.map[1][x0][y0][z0][2]==6 then
				if not draw.p[1] or not draw.p[2] then
					collide(x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 94)
				else
					collide(x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 2)
					collide(x0 * 96, y0 * 128 + 2, z0 * 96 + 94, x0 * 96, y0 * 128 + 126, z0 * 96 + 94)
					collide(x0 * 96, y0 * 128 + 126, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 94)
				end
			elseif draw.map[1][x0][y0][z0][2]==7 then
				if coll(clx - 24,  cly - 24, clz - 24, clx + 24,  cy + 24, clz + 24, x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 94) then bf = true end		
			elseif draw.map[1][x0][y0][z0][2]==11 then
				collide(x0 * 96, y0 * 128 + 2, z0 * 96 + 62, x0 * 96, y0 * 128 + 126, z0 * 96 + 94)
			elseif draw.map[1][x0][y0][z0][2]==12 then
				collide(x0 * 96, y0 * 128 + 2, z0 * 96 + 2, x0 * 96, y0 * 128 + 126, z0 * 96 + 34)
			end

			if draw.map[2][x0][y0][z0][2] > 0 and draw.map[2][x0][y0][z0][2]~=5 and draw.map[2][x0][y0][z0][2]~=8 and draw.map[2][x0][y0][z0][2]~=9 then
				collide(x0 * 96 + 2, y0 * 128, z0 * 96 + 2, x0 * 96 + 94, y0 * 128, z0 * 96 + 94)
			elseif draw.map[2][x0][y0][z0][2]==8 or draw.map[2][x0][y0][z0][2]==9 then
				if coll(clx - 24, cly - 24, clz - 24, clx + 24, cly + 24, clz + 24, x0 * 96 + 2, y0 * 128, z0 * 96 + 2, x0 * 96 + 94, y0 * 128, z0 * 96 + 94) then draw.objects.c[i].vy=12 sfx_(0,"C-6",-1,1) end
			end

			if wall_coll[draw.map[3][x0][y0][z0][2]] then
				collide(x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96)
			elseif draw.map[3][x0][y0][z0][2]==5 or draw.map[3][x0][y0][z0][2]==6 then
				if not draw.p[1] or not draw.p[2] then
					collide(x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96)
				else
					collide(x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 2, y0 * 128 + 126, z0 * 96)
					collide(x0 * 96 + 94, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96)
					collide(x0 * 96 + 2, y0 * 128 + 126, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96)
				end
			elseif draw.map[3][x0][y0][z0][2]==7 then
				if coll(clx - 24, cly - 24, clz - 24, clx + 24, cly + 24, clz + 24, x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96) then bf=true end
			elseif draw.map[3][x0][y0][z0][2]==11 then
				collide(x0 * 96 + 62, y0 * 128 + 2, z0 * 96, x0 * 96 + 94, y0 * 128 + 126, z0 * 96)
			elseif draw.map[3][x0][y0][z0][2]==12 then
				collide(x0 * 96 + 2, y0 * 128 + 2, z0 * 96, x0 * 96 + 34, y0 * 128 + 126, z0 * 96)
			end

		end end end
		--collision with the player
		if not plr.noclip then --Correct the mystical disappearance of cubes when span through them
			local x0=plr.x
			local y0=plr.y
			local z0=plr.z
			collide(x0 - 16, y0 - 64, z0 - 16, x0 + 16, y0 + 16, z0 + 16)
		end

		--collision with objects
		for i2=1,#draw.objects.c do
			if i2~=i then
				local x0=draw.objects.c[i2].x
				local y0=draw.objects.c[i2].y
				local z0=draw.objects.c[i2].z
				obj_collide(1, x0, y0, z0)
				if draw.objects.c[i2].inp and draw.p[1] and draw.p[2] then
					x0=draw.objects.c[i].x1
					y0=draw.objects.c[i].y1
					z0=draw.objects.c[i].z1
					obj_collide(1, x0, y0, z0)
				end
			end
		end

		-- cube special cases

		for i2=1,#draw.objects.lb do
			local x0=draw.objects.lb[i2].x
			local y0=draw.objects.lb[i2].y+5 -- <--
			local z0=draw.objects.lb[i2].z
			obj_collide(draw.objects.lb[i].type , x0, y0, z0)
		end

		for i2=1,#draw.objects.fb do --exception for cubes
			local x0=draw.objects.fb[i2].x
			local y0=draw.objects.fb[i2].y
			local z0=draw.objects.fb[i2].z
			collide(x0 - 37, y0, z0 - 37, x0 + 37, y0 + 7, z0 + 37)
		end

		local object_types = {"b", "t", "l"}
		for _,type in ipairs(object_types) do
			for _,obj in ipairs(draw.objects[type]) do
				local x0, y0, z0 = obj.x, obj.y, obj.z
				obj_collide(obj.type, x0, y0, z0)
			end
		end

		--
		draw.objects.c[i].x = cx
		draw.objects.c[i].y = cy
		draw.objects.c[i].z = cz
		--
		if bf or draw.objects.c[i].y<-200 then
			sfx_(2)
			--particles
			for i2=1,80 do
				addp(cx-24       ,cy+R(-24,24),cz+R(-24,24),R()*2-1,R()*2-1,R()*2-1,R(30,60),1)
				addp(cx+24       ,cy+R(-24,24),cz+R(-24,24),R()*2-1,R()*2-1,R()*2-1,R(30,60),1)
				addp(cx+R(-24,24),cy-24       ,cz+R(-24,24),R()*2-1,R()*2-1,R()*2-1,R(30,60),1)
				addp(cx+R(-24,24),cy+24       ,cz+R(-24,24),R()*2-1,R()*2-1,R()*2-1,R(30,60),1)
				addp(cx+R(-24,24),cy+R(-24,24),cz-24       ,R()*2-1,R()*2-1,R()*2-1,R(30,60),1)
				addp(cx+R(-24,24),cy+R(-24,24),cz+24       ,R()*2-1,R()*2-1,R()*2-1,R(30,60),1)
			end
			--
			local i2=draw.objects.c[i].disp
			draw.objects.cd[i2].t=60
			draw.objects.cd[i2].ct=draw.objects.c[i].type
			--
			table.remove(draw.objects.c,i)
			i=i-1
		end
		--
	until i>=#draw.objects.c
end

function unitic.render() -------- 
	--dynamic textures
	for x0=0,15 do --light bridge
		for y0=0,11 do setpix(x0,y0+234,15) end
		local y0=(math.sin((-t%30+x0*2)/5)+1)*6
		local y1=(math.cos((-t%30+x0*2)/5)+1)*6
		local y2=(math.sin(t/20)+1)*6
		setpix(x0,F(y0)+234,11)
		setpix(x0,F(y1)+234,10)
		setpix(x0,F(y2)+234,11)
	end
	--blue / red field
	for y0=0,31,2 do
		if b_f[y0].d then
			setpix((b_f[y0][1]+t//2)%24+24,y0+32,b_f[y0][3])
			setpix((b_f[y0][2]+t//2)%24+24,y0+32,15)
			--red field
			setpix((b_f[y0][1]+t//2)%24+96,y0+64,b_f[y0][3]-2)
			setpix((b_f[y0][2]+t//2)%24+96,y0+64,15)

			setpix((b_f[y0][1]+t//2)%24+96,y0+152,b_f[y0][3]-2)
			setpix((b_f[y0][2]+t//2)%24+96,y0+152,15)
		end
		if b_f[y0+1].d then
			setpix((b_f[y0+1][1]+t//2*23)%24+24,y0+33,15)
			setpix((b_f[y0+1][2]+t//2*23)%24+24,y0+33,b_f[y0+1][3])
			--red field
			setpix((b_f[y0+1][1]+t//2*23)%24+96,y0+65,15)
			setpix((b_f[y0+1][2]+t//2*23)%24+96,y0+65,b_f[y0+1][3]-2)

			setpix((b_f[y0+1][1]+t//2*23)%24+96,y0+153,15)
			setpix((b_f[y0+1][2]+t//2*23)%24+96,y0+153,b_f[y0+1][3]-2)
		end
	end
	--particles
	for i=1,#draw.pr_g do
		local  x=draw.pr_g[i][1]*96
		local  y=draw.pr_g[i][2]*128+4
		local  z=draw.pr_g[i][3]*96
		local vx=draw.pr_g[i][4]
		local vz=draw.pr_g[i][5]
		for i=0,15 do
			if     vx==-1 then addp(x+96,y,z+i*6, R(1,4),R(-2,2), R(-2,2),R(2,10),R(10,11))
			elseif vx==1  then addp(x   ,y,z+i*6,-R(1,4),R(-2,2), R(-2,2),R(2,10),R(10,11))
			elseif vz==-1 then addp(x+i*6,y,z+96, R(-2,2),R(-2,2), R(1,4),R(2,10),R(10,11))
			elseif vz==1  then addp(x+i*6,y,z   , R(-2,2),R(-2,2),-R(1,4),R(2,10),R(10,11))
			end
		end
	end
	--
	cam.x, cam.y, cam.z, cam.tx, cam.ty = plr.x, plr.y, plr.z, plr.tx, plr.ty
	unitic.update_pr()
	unitic.update()
	if plr.y>=0 then unitic.draw_grid() end
	unitic.draw()
	if plr.y<0 then unitic.draw_grid() end
	--cross
	pix(120,68,7)
end

function unitic.draw_grid()
	for x = 0, world_size[1]-1 do
		for z = 0, world_size[3]-2 do
			local p1=unitic.poly.v[x + z*world_size[4]+1]
			local p2=unitic.poly.v[x + (z+1)*world_size[4]+1]

			line(p1[1],p1[2], p2[1],p2[2],0)

			local p3=unitic.poly.v[z + x*world_size[4]+1]
			local p4=unitic.poly.v[z + x*world_size[4]+2]
			line(p3[1],p3[2], p4[1],p4[2],0)
		end
	end
end
--map
local walls = {}
local objects = {}
local walls_bytes = {}
local objs_bytes = {}
for i = 1,#objects_data.names do objects[i]={} end

local function import()
	walls = {}
	walls_bytes = {}
	objs_bytes = {}

	for i=1,3 do
		draw.map[i]={}
		for x=0,world_size[1]-1 do
			draw.map[i][x]={}
			for y=0,world_size[2]-1 do
				draw.map[i][x][y]={}
				for z=0,world_size[3]-1 do
					draw.map[i][x][y][z]={0,0,0,0}
				end
			end
		end
	end

	--walls
	local adr = 0
	while true do
		local bytes = (peek(0x08000 + adr * 3)<<16) + (peek(0x08000 + adr * 3 + 1)<<8) + peek(0x08000 + adr * 3 + 2)

		if bytes == 0 or adr>5440 then break end
		local type  = bytes % (1<<6)   bytes = bytes >> 6
		local face  = bytes % (1<<2)   bytes = bytes >> 2
		local angle = bytes % (1<<2)   bytes = bytes >> 2
		local z = bytes % (1<<4)   bytes = bytes >> 4
		local y = bytes % (1<<4)   bytes = bytes >> 4
		local x = bytes % (1<<4)   bytes = bytes >> 4

		adr = adr + 1

		walls_bytes[#walls_bytes+1] = addwall(x, y, z, angle, face, type, adr)
		walls[#walls+1] = {x, y, z, angle, face, type}
	end
	
	menu.w.sel = #walls

	--objects
	adr = 0
	while true do
		local bytes = 0
		for i = 0, 5 do
			bytes = (bytes<<8) + peek(0x08000 + 3 + #walls * 3 + adr * 6 + i)
		end

		if bytes == 0 or adr > 2968 then break end

		adr = adr + 1

		bytes = bytes >> 4
		local t1   = bytes % (1<<5) bytes = bytes >> 5
		local type = bytes % (1<<5) bytes = bytes >> 5
		local z = bytes % (1<<12) - 1520 bytes = bytes >> 12
		local y = bytes % (1<<10) - 116  bytes = bytes >> 10
		local x = bytes % (1<<12) - 1520 bytes = bytes >> 12

		objs_bytes[#objs_bytes+1] = addobj(x, y, z, type, t1)

		local tab = 0

		for i = 1, #objects_data.types do
			for i2 = 1,#objects_data.types[i] do
				if type == objects_data.types[i][i2] then tab = i break end
			end
		end

		if tab ~= 0 then
			objects[tab][#objects[tab]+1] = {x, y, z, type, t1}
		end
	end
end

local function export()
	memset(0x08000, 0, 240*136)
	for i = 1, #walls_bytes do
		poke(0x08000 + (i-1)*3    , walls_bytes[i]>>16)
		poke(0x08000 + (i-1)*3 + 1, walls_bytes[i]>>8)
		poke(0x08000 + (i-1)*3 + 2, walls_bytes[i])
	end

	local addr = 0x08000 + #walls_bytes * 3 + 3 -- 3 zero bytes mean that objects will be indicated further

	for i = 1, #objs_bytes do
		local bytes = objs_bytes[i]
		for i2 = 5, 0,-1 do
			poke(addr + (i-1)*6 + 5 - i2, (bytes >> (8 * i2))&0xFF)
		end
	end
	
	sync(4, map_bank, true)
end

function addwall(x, y, z, angle, face, type,i)
	local bytes = 0 --converting a wall to bytes (3 bytes per wall)

	bytes = (bytes<<4) + x -- 4 bites
	bytes = (bytes<<4) + y -- 4 bites
	bytes = (bytes<<4) + z -- 4 bites
	bytes = (bytes<<2) + angle -- 2 bites
	bytes = (bytes<<2) + face  -- 2 bites
	bytes = (bytes<<6) + type  -- 6 bites
	draw.map[angle][x][y][z]={face,type,i, bytes}
	return bytes
end

function upd_walls()
	for i=1,3 do
		draw.map[i]={}
		for x=0,world_size[1]-1 do
			draw.map[i][x]={}
			for y=0,world_size[2]-1 do
				draw.map[i][x][y]={}
				for z=0,world_size[3]-1 do
					draw.map[i][x][y][z]={0,0,0,0}
				end
			end
		end
	end

	walls_bytes = {}

	for i=1,#walls do
		local wall = walls[i]

		if wall[7] then
			for x = min(wall[1],wall[8]), max(wall[1],wall[8]) do
				for y = min(wall[2],wall[9]), max(wall[2],wall[9]) do
					for z = min(wall[3],wall[10]), max(wall[3],wall[10]) do
						walls_bytes[#walls_bytes+1] = addwall(x,y,z,wall[4],wall[5],wall[6],i)
					end
				end
			end
		else
			walls_bytes[#walls_bytes+1] = addwall(wall[1],wall[2],wall[3],wall[4],wall[5],wall[6],i)
		end
	end
	update_world()

	export()
end

function addobj(x, y, z, type,t1) --objects
	local bytes = 0 --converting a object to bytes (6 bytes per objects)

	bytes = (bytes<<12) + x + 1520 -- 12 bites
	bytes = (bytes<<10) + y + 116  -- 10 bites
	bytes = (bytes<<12) + z + 1520 -- 12 bites
	bytes = (bytes<<5 ) + type --5 bites
	bytes = (bytes<<5 ) + (t1 or 0) --5 bites
	bytes = (bytes<<4 ) + 15 --4 bits are not used

	if type==1 or type==2 then --cubes
		draw.objects.c[#draw.objects.c+1]=
		{type=type, --type
		id=#draw.objects.c+1, --id
		x=x,y=y,z=z, --object coordinates
		vx=0, vy=0, vz=0, --velocity
		draw=true, --whether to display the model
		disp=t1, -- cube dispenser ID
		model=model[type]}
	elseif type==3 then --cube dispenser
		draw.objects.cd[#draw.objects.cd+1]=
		{type=type,
		id=#draw.objects.cd+1,
		x=x,y=y,z=z,
		draw=true,
		t=0,ct=0, --cube type
		model=model[type]}
	elseif type==4 or type==5 or type==6 or type==7 then --light bridges
		draw.objects.lb[#draw.objects.lb+1]=
		{type=type,
		id=#draw.objects.lb+1,
		x=x,y=y,z=z,
		draw=true,
		model=model[type]}
	elseif type==8 or type==9 or type==10 or type==11 then --buttons
		draw.objects.b[#draw.objects.b+1]=
		{type=type,
		id=#draw.objects.b+1,
		x=x,y=y,z=z,
		t=t1 or (math.huge), --button press time (math.huge for a constant signal, -1 to switch the signal)
		t1=0,
		tick=false, --sends a signal 1 tick long while pressing the button
		s=false, --button signal
		draw=true,model={v=model[type].v,f=model[type].f}}
	elseif type==12 or type==13 or type==14 or type==15 then --turrets
		draw.objects.t[#draw.objects.t+1]=
		{type=type,
		id=#draw.objects.t+1,
		x=x,y=y,z=z,
		cd=0,
		draw=true,model=model[type]}
	elseif type==16 then --floor button
		draw.objects.fb[#draw.objects.fb+1]=
		{type=type,
		id=#draw.objects.fb+1,
		x=x,y=y,z=z,
		tick=false,
		s=false,
		draw=true,model={v=model[type].v,f=model[type].f}}
	elseif type==17 or type==18 or type==19 or type==20 then --lifts
		draw.objects.l[#draw.objects.l+1]=
		{type=type,
		id=#draw.objects.l+1,
		x=x,y=y,z=z,
		draw=true,model=model[type]}
	elseif type==21 or type==22 or type==23 or type==24 then --display
		draw.objects.d[#draw.objects.d+1]=
		{type=type,
		id=#draw.objects.d+1,
		x=x,y=y,z=z,
		s=false, --signal
		draw=true,model={v=model[type].v,f=model[type].f}}

	elseif type<=#model and type>0 then error("unknown object | "..type) else error("unknown type | "..type) end

	return bytes
end

function upd_objs()
	draw.objects = {c={},cd={},lb={},b={},t={},fb={},l={},d={}}

	objs_bytes = {}

	for i=1,#objects do
		for i2=1,#objects[i] do
			objs_bytes[#objs_bytes+1] = addobj(objects[i][i2][1],objects[i][i2][2],objects[i][i2][3],objects[i][i2][4])
		end
	end

	export()
end

function update_world()
	draw.world.f={}
	draw.pr_g={}

	for i=0,(world_size[1]-1)*(world_size[2]-1)*(world_size[3]-1) do draw.world.v[i+1][4] = false end

	for angle=1,3 do for x0=0,world_size[1]-1 do for y0=0,world_size[2]-1 do for z0=0,world_size[3]-1 do
		local face = draw.map[angle][x0][y0][z0][1]
		local type = draw.map[angle][x0][y0][z0][2]
		local id   = draw.map[angle][x0][y0][z0][3]

		if angle == 2 and (type == 6 or type>9) then type = 7 end
		if angle ~= 2 and type == 5 then type = 6 end

		type = type - 1
		local type1 = type%5
		local type2 = type//5
		------
		if type~=-1 then
			if angle==1 then
				table.insert(draw.world.f,{w={face,angle,x0,y0,z0,id,1},x0+y0*world_size[3]+z0*world_size[4]+1,x0+y0*world_size[3]+z0*world_size[4]+world_size[4]+1,x0+y0*world_size[3]+z0*world_size[4]+world_size[3]+1,f=face,uv={x={24+type1*24,type1*24,24+type1*24},y={32+type2*32,32+type2*32,0+type2*32}}})
				table.insert(draw.world.f,{w={face,angle,x0,y0,z0,id,2},x0+y0*world_size[3]+z0*world_size[4]+world_size[4]+1,x0+y0*world_size[3]+z0*world_size[4]+world_size[4]+world_size[3]+1,x0+y0*world_size[3]+z0*world_size[4]+world_size[3]+1,f=face,uv={x={type1*24,type1*24,24+type1*24},y={32+type2*32,0+type2*32,0+type2*32}}})
				--
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+1][4]=true
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+world_size[4]+1][4]=true
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+world_size[3]+1][4]=true
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+world_size[4]+world_size[3]+1][4]=true
			end

			if angle==2 then
				table.insert(draw.world.f,{w={face,angle,x0,y0,z0,id,1},x0+y0*world_size[3]+z0*world_size[4]+1,x0+y0*world_size[3]+z0*world_size[4]+2,x0+y0*world_size[3]+z0*world_size[4]+world_size[4]+1,f=face,uv={x={0+type1*24,0+type1*24,24+type1*24},y={152+type2*24,176+type2*24,152+type2*24}}})
				table.insert(draw.world.f,{w={face,angle,x0,y0,z0,id,2},x0+y0*world_size[3]+z0*world_size[4]+2,x0+y0*world_size[3]+z0*world_size[4]+world_size[4]+2,x0+y0*world_size[3]+z0*world_size[4]+world_size[4]+1,f=face,uv={x={0+type1*24,24+type1*24,24+type1*24},y={176+type2*24,176+type2*24,152+type2*24}}})
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+1][4]=true
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+2][4]=true
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+world_size[4]+1][4]=true
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+world_size[4]+2][4]=true
			end

			if angle==3 then
				table.insert(draw.world.f,{w={face,angle,x0,y0,z0,id,1},x0+y0*world_size[3]+z0*world_size[4]+1,x0+y0*world_size[3]+z0*world_size[4]+2,x0+y0*world_size[3]+z0*world_size[4]+world_size[3]+1,f=face,uv={x={24+type1*24,type1*24,24+type1*24},y={32+type2*32,32+type2*32,0+type2*32}}})
				table.insert(draw.world.f,{w={face,angle,x0,y0,z0,id,2},x0+y0*world_size[3]+z0*world_size[4]+2,x0+y0*world_size[3]+z0*world_size[4]+world_size[3]+2,x0+y0*world_size[3]+z0*world_size[4]+world_size[3]+1,f=face,uv={x={type1*24,type1*24,24+type1*24},y={32+type2*32,0+type2*32,0+type2*32}}})
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+1][4]=true
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+2][4]=true
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+world_size[3]+2][4]=true
				draw.world.v[x0+y0*world_size[3]+z0*world_size[4]+world_size[3]+1][4]=true
			end


			if face == 2 and (angle == 1 or angle == 3) then
				local idx = #draw.world.f
				for i = 1, 3 do
					draw.world.f[idx - 1].uv.x[i] = (2 * type1 + 1) * 24 - draw.world.f[idx - 1].uv.x[i]
					draw.world.f[idx].uv.x[i] = (2 * type1 + 1) * 24 - draw.world.f[idx].uv.x[i]
				end
			end
		end
		------
	end end end end
	--light bridge generator
	draw.objects.lb={}
	draw.world.sp={}
	if draw.lg~=0 then
		for i=1,#draw.lg do
			local lx,ly,lz=draw.lg[i][1],draw.lg[i][2],draw.lg[i][3]
			local vx,vz=0,0
			if     draw.lg[i][4]==1 and draw.lg[i][5]==1 then vx=-1 lx=lx-1
			elseif draw.lg[i][4]==1 and draw.lg[i][5]==2 then vx=1
			elseif draw.lg[i][4]==3 and draw.lg[i][5]==1 then vz=1
			elseif draw.lg[i][4]==3 and draw.lg[i][5]==2 then vz=-1 lz=lz-1 else error(draw.lg[i][4].." | "..draw.lg[i][5])
			end
			for _=1,100 do --bridge lenght limiter
				if     vx==-1 then addobj(48+lx*96,ly*128,48+lz*96,4)
				elseif vx==1  then addobj(48+lx*96,ly*128,48+lz*96,5)
				elseif vz==-1 then addobj(48+lx*96,ly*128,48+lz*96,6)
				elseif vz==1  then addobj(48+lx*96,ly*128,48+lz*96,7)
				end

				lx=lx+vx
				lz=lz+vz

				--if the bridge collides with a wall, we stop the loop
				if lx<0 or lx>world_size[1]-1 or lz<0 or lz>world_size[3]-1 then draw.pr_g[#draw.pr_g+1]={lx,ly,lz,vx,vz} break end
				if (vx==1  and draw.map[1][lx  ][ly][lz  ][2]~=0 and draw.map[1][lx  ][ly][lz  ][2]~=3 and draw.map[1][lx  ][ly][lz  ][2]~=15)
				or (vx==-1 and draw.map[1][lx+1][ly][lz  ][2]~=0 and draw.map[1][lx+1][ly][lz  ][2]~=3 and draw.map[1][lx+1][ly][lz  ][2]~=15)
				or (vz==1  and draw.map[3][lx  ][ly][lz  ][2]~=0 and draw.map[3][lx  ][ly][lz  ][2]~=3 and draw.map[3][lx  ][ly][lz  ][2]~=15)
				or (vz==-1 and draw.map[3][lx  ][ly][lz+1][2]~=0 and draw.map[3][lx  ][ly][lz+1][2]~=3 and draw.map[3][lx  ][ly][lz+1][2]~=15) then draw.pr_g[#draw.pr_g+1]={lx,ly,lz,vx,vz} break
				end
			end
		end
	end
end

local function load_world() --Loads the world from the map RAM
	--init
	draw.map={}
	draw.world={v={},f={},sp={}}
	draw.pr={}
	draw.pr_g={}
	draw.lg={}
	draw.objects={
		c={}, --cubes
		cd={}, --cube dispensers
		lb={}, --light bridges
		b={}, --buttons
		t={}, --turrets
		fb={}, --floor button
		l={}, --lifts
		d={} --displays
	}

	for z=0,world_size[1]-1 do for y=0,world_size[2]-1 do for x=0,world_size[3]-1 do
		table.insert(draw.world.v,{x*96,y*128,z*96,false}) --this boolean is resposible for whether the point needs to be updated or not
		--addp(x*96,y*128,z*96,0,0,0, math.huge,0)
	end end end

	import()
	----
	update_world()
end
--palette
local pal="0000001c181c3838385d5d5d7d7d7dbababad6d6d6fffffff21018ff55553499ba65eef6b2f6faff8d18ffbe3c283040"

function savepal()
	local pal_1={}
	for i=0,48 do
		local val=peek(0x3FC0+i)
		pal_1[i]=val
	end
	return pal_1
end

function loadpal(pal_1)
	for i=0,48 do
		poke(0x3FC0+i,pal_1[i])
	end
end

function respal()
	for i=1,#pal,2 do
		poke(0x3FC0+i//6*3+i//2%3,tonumber(pal:sub(i,i+1),16))
	end
end

function updpal(r,g,b)
	for i=0,47,3 do
		poke(0x03FC0+i,peek(0x03FC0+i)*r) --RLUE
		poke(0x03FC1+i,peek(0x03FC1+i)*g) --BREEN
		poke(0x03FC2+i,peek(0x03FC2+i)*b) --GED
	end
end

function darkpal(c)
	for i=0,47 do --RGB
		poke(0x03FC0+i,peek(0x03FC0+i)*c)
	end
end

local x_p={x=0, y=7, mx=0, my=0, type=2, drag = false} --xyz pointer

local function xyz_pointer(p_x,p_y, type, len)
	if type == 0 then return end
	len = len or 12
   local xyz2={{0,0,-1,1},{0,0,-1,2},{0,0,-1,3}} --2d coordinates, depth, color
   local xyz3={{1,0,0,1},{0,1,0,2},{0,0,1,3}} --3d coordinates, color
   --magic
   for u=1,3 do
      --rotate
      local a1=xyz3[u][1]
      local b1=xyz3[u][2]
      local c1=xyz3[u][3]

      local c2=c1*math.cos(-cam.ty)-a1*math.sin(-cam.ty)
      local a2=c1*math.sin(-cam.ty)+a1*math.cos(-cam.ty)
      local b2=b1

      local b3=b2*math.cos(cam.tx)-c2*math.sin(cam.tx)
      local c3=b2*math.sin(cam.tx)+c2*math.cos(cam.tx)
      local a3=a2

      xyz3[u][1]=a3
      xyz3[u][2]=b3
      xyz3[u][3]=min(c3,-1)

      xyz2[u][1]=len*xyz3[u][1]/xyz3[u][3]+15+p_x
      xyz2[u][2]=len*xyz3[u][2]/xyz3[u][3]+15+p_y
      xyz2[u][3]=c3
   end --the end of the magic
	--sort
	local xyz2_2 = {xyz2[1], xyz2[2], xyz2[3]}

	table.sort(xyz2,function(a,b)return a[3]<b[3]end)
	--render
	local colors = {10,13,8}
	for i = 1,3 do
		line(xyz2[i][1], xyz2[i][2], 15+p_x, 15+p_y, colors[xyz2[i][4]])
		pix(15+p_x, 15+p_y,7)
		if type==2 then spr(399+xyz2[i][4], xyz2[i][1]-2, xyz2[i][2]-3, 15) end
	end

	return xyz2_2
end

local fix_mouse = false
local function show_cursor()
	if peek(0x7FC3F, 1) == 0 then return end

	poke(0x7FC3F, 0, 1)
	fix_mouse = true
end

local avf={} --average frame
local fr={0,0,0} --framerate

local f_m = false --fixed mouse cursor
local fmt = 0
--init
local state
local tm1,tm2 = 0,0
local p={t=0} --pause
local ms={b={}} --main screen | Table with current buttons
local mbc = 0 --map bank id
--buttons
local menu_options --It must be separate, otherwise local variables inside this table may not see each other

local function load_map_bank(i)
	ms.b = menu_options.mb
	map_bank_state[map_bank+1] = (#walls~=0)
	state="edit"
	poke(0x7FC3F,1,1)
	map_bank = i
	sync(4, map_bank, false)
	pmem(0, map_bank)
	load_world()
	trace("Current bank: "..map_bank,3)
end

menu_options = {
	p = { --pause
		{draw = true, y = 65, t=1, text = "Resume"       , func = function() state="edit" sfx_(17) poke(0x7FC3F,1,1) end},
		{draw = true, y = 85, t=1, text = "select a map bank", func = function() ms.b = menu_options.mb sfx_(16)end},
		{draw = true, y = 95, t=1, text = "Clear the map", func = function() state = "clear confirm" ms.b = menu_options.cc sfx_(16) end}
	},
	mb = { --map bank select
		{draw = true, y =  45, t=1, text = "Map bank 0", func = function()load_map_bank(0)end},
		{draw = true, y =  55, t=1, text = "Map bank 1", func = function()load_map_bank(1)end},
		{draw = true, y =  65, t=1, text = "Map bank 2", func = function()load_map_bank(2)end},
		{draw = true, y =  75, t=1, text = "Map bank 3", func = function()load_map_bank(3)end},
		{draw = true, y =  85, t=1, text = "Map bank 4", func = function()load_map_bank(4)end},
		{draw = true, y =  95, t=1, text = "Map bank 5", func = function()load_map_bank(5)end},
		{draw = true, y = 105, t=1, text = "Map bank 6", func = function()load_map_bank(6)end},
		{draw = true, y = 115, t=1, text = "Map bank 7", func = function()load_map_bank(7)end},
		{draw = true, y = 125, t=1, text = "Back", func = function() ms.b = menu_options.p sfx_(17)end},
	},
	cc = {	--clear confirm
	{draw = true, y = 105, t=1, text = "Accept", func = function()
		state="edit" sfx_(17) poke(0x7FC3F,1,1)
		for i = 1,#objects_data.names do menu.o.sel[i] = 0 objects[i]={} end
		menu.w.sel = 0
		walls={}
		upd_walls()
		upd_objs()
	end},
	{draw = true, y = 115, t=1, text = "Cancel", func = function() state="pause" ms.b = menu_options.p sfx_(17) end},
	}
}

local function upd_buttons()
	for i = 1, #ms.b do
		local b = ms.b[i]
		if b.draw then
			if ms.b == menu_options.mb and i<9 then
				if map_bank == i-1 then
					print(b.text, min(24-b.t*20), b.y, 11)
					print("Current", 192, b.y, 11)
				elseif map_bank_state[i]  then
					print(b.text, min(24-b.t*20), b.y, 7)
				else
					print("Empty", 198, b.y, 2)
					print(b.text, min(24-b.t*20), b.y, 2)
				end

			else
				print(b.text, min(24-b.t*20), b.y, 7)
			end

			if my > b.y - 3 and my < b.y + 8 then
				b.t = max(b.t-0.05,0.5)
				cid = 1
				if clp1 then b.func() break end
			else
				b.t = min(1,b.t+0.05)
			end
		end
	end
end

local function upd_buttons_bdr(bdr_y,orig_pal)
	if bdr_y == 0 then
		orig_pal()
	end
	for i = 1, #ms.b + 1 do
		local b
		local lb
		if i<=#ms.b then b = ms.b[i] end
		if i>1 then lb = ms.b[i-1] end

		if lb and lb.draw and lb.y == bdr_y - 8 then
			orig_pal()
		end
		
		if b and b.draw and b.y == bdr_y + 2 then
			darkpal(b.t)
		end

	end
end

local function button(bx,by,bw,bh,cursor)
	if mx>=bx and my>=by and mx<bx+bw and my<by+bh then
		-- rectb(bx,by,bw,bh,13)
		if cursor~=false then cid=1 end --true or nil
		return true
	end
end

local function print_mid(text,x,y,color)
	local text_size=print(text,240,0)
	print(text,x - text_size//2, y, color)
end

local function clip_val(val, min_v,max_v)
	if val<min_v then return min_v end
	if val>max_v then return max_v end
	return val
end

menu = {
	open = true,
	type = 1,
	w={ --walls editor
		sel = 0, --select wall id
		m_sel = -1, --mouse selection
		sl = {id=0, val=0, val_2=0 , t=0, n= false} --slider
	},
	o={ --object editor
		tab = 1,
		sel = {}, --unique for each tab
		sl = {id=0, val=0, val_2=0 , t=0, n= false}, --slider
		magnet = false,
		m_sel = 0, --select obj id
		m_tab = 0, --select obj tab
	}
}

for i = 1,#objects_data.names do menu.o.sel[i] = 0 end

state="map_bank_check"

sync(4, map_bank, false)
function TIC()
	--counters
	t1 = time()
	t = t + 1
	--mouse
	mx, my, cl1, _, cl2, _, whl = mouse()
	cid=0 --cursor id

	local nclp2 = not clp2 and tm2~=0
	ins = true --is the cursor in the scene

	sc1 = tm1 <= 15 and tm1>0 and not cl1 --short click

	if cl1 then tm1 = tm1 + 1 else tm1 = 0 end
	if cl2 then tm2 = tm2 + 1 else tm2 = 0 end

	clp1 = tm1 == 1
	clp2 = tm2 == 1
	--------------------------
	-- map bank check --------
	--------------------------
	if state=="map_bank_check" then
		cls(0)
		print("Please wait...",85,63,1)
		if mbc >= 8 then
			sync(4, map_bank, false)
			state = "load lvl"
		else
			sync(4, mbc, false)
		end

		map_bank_state[mbc+1] = false
		for i = 0, 240*136-1 do
			if peek(0x08000+i) ~=0 then map_bank_state[mbc+1] = true break end
		end

		mbc = mbc + 1
	end
	--------------------------
	-- load lvl --------------
	--------------------------
	if state=="load lvl" then
		load_world()
		--
		mx,my=0,0
		poke(0x7FC3F,1,1)
		state="edit"
	end
	--------------------------
	-- pause -----------------
	--------------------------
	if state=="pause" or state=="clear confirm" then
		p.t=p.t+1
		--GUI
		vbank(0)
		memcpy(0x0,0x8000,240*136/2)
		vbank(1)
		cls(0)
		--logo
		spr(256,min(-104+p.t*6,8),4,0,1,0,0,13,3)

		print("Pause",min(p.t*2,37),35,7)
		upd_buttons()

		if state=="clear confirm" then
			print("Clear the map? This",4,65,8)
			print("Cannot be undone!",4,75,8)
		end
		--Resume
		if (keyp(44) and p.t>1) or (my>52 and my<63 and clp1 and state=="pause") then
			state="edit"
			sfx_(17)
			poke(0x7FC3F,1,1)
		 end
	end
	--------------------------
	-- game ------------------
	--------------------------
	if state=="edit" then
	 --counters
		if stt~=120 then stt=stt+1 end
	--palette
		for i = 0,1 do
			vbank(i)
			respal()
		end
		vbank(0)

		if f_m then darkpal(0.85) else darkpal(0.6) end
	 --camera rotation
		fmt = fmt + 1
		if keyp(26) then fmt=0 f_m = not f_m mx,my = 0,0 end
		if clp2 then fmt=0 mx,my=0,0 end

		if cl2 then f_m = true
		elseif nclp2 then f_m = false end
		if not menu.w.sl.n and not menu.o.sl.n then
			if f_m then
				poke(0x7FC3F,1,1)
			else
				show_cursor()
			end
		end

	 	if p.t==0 and stt>2 and f_m and fmt>1 then
			if key(65) then --zoom
				plr.tx = plr.tx + my/800
				plr.ty = plr.ty + mx/800
			else
				plr.tx = plr.tx + my/80
				plr.ty = plr.ty + mx/80
			end
	 	end
		plr.ty = plr.ty%(math.pi*2)
		plr.tx = max(min(plr.tx, pi2), -pi2)
	 --update + collision
		unitic.player_physics()
	 --render
		vbank(0)
		cls(15)
		unitic.render()
		memcpy(0x8000,0x0000,240*136/2)
		vbank(1)
		memcpy(0x0000,0x8000,240*136/2)
	 --sounds
		s.t1=max(s.t1-1,0)
		if (key(23) or key(19) or key(1) or key(4)) and s.t1==0 then sfx_(1) if key(64) then s.t1=15 else s.t1=20 end end
	 --pause
		if keyp(44) and p.t==0 then vbank(0) memcpy(0x8000,0x0000,240*136/2) state="pause" ms.b = menu_options.p for i=1,3 do s.n[i]=peek(0x13FFB+i) end music(3,7,0) show_cursor() end
		p.t=0
	 --debug
	 	local debug_text={
			"FPS:  " .. F(1000 / fr[1]).."|"..F(1000 / (fr[3]+fr[2])*2).."  Frame:"..F(fr[1]+0.5).."|"..F((fr[3]+fr[2])/2+0.5).."  ms.".." v: " .. #unitic.poly.v .. " f:" .. #unitic.poly.f,
			"walls:"..#walls.." particles:"..#unitic.p.." objects:"..#unitic.obj,
			"camera X:" .. F(plr.x) .. " Y:" .. F(plr.y) .. " Z:" .. F(plr.z),
		}
	 --top debug panel
		if keyp(49) then
				plr.dt=plr.dt%#debug_text+1
		end
		local top_text=debug_text[plr.dt]
	 --bottom debug panel
		if plr.noclip then rect(0,129,35,7,0) print("Noclip", 2, 130, 7) end
		rect(0,0,240,7,0)
		line(220,0,220,6,7)
		line(230,0,230,6,7)
		if my<7 or mx<0 or mx>239 or my>135 then ins = false end
		if menu.open then
			if menu.type==1 then
				rect(220,0,10,7,7)
				spr(501,223,1,15)
				spr(502,233,1,15)
			else
				rect(230,0,10,7,7)
				spr(500,223,1,15)
				spr(503,233,1,15)
			end
		else
			spr(500,223,1,15)
			spr(502,233,1,15)
		end

		if button(231,0,9,7) then
			top_text = "Objects editor"
			if clp1 then
				if not menu.open then menu.open = true menu.type = 2
				elseif menu.open and menu.type==1 then menu.type = 2
				elseif menu.open and menu.type==2 then menu.open = false
				end
			end
		end
		
		if button(221,0,9,7) then
			cid=1
			top_text = "walls and floor editor"
			if clp1 then
				if not menu.open then menu.open = true menu.type = 1
				elseif menu.open and menu.type==2 then menu.type = 1
				elseif menu.open and menu.type==1 then menu.open = false
				end
			end
		end
		--xyz pointer
		if x_p.type ~=0 then
			if x_p.type<3 then rect(x_p.x,x_p.y,30,30,0) end
			xyz_pointer(x_p.x, x_p.y, (x_p.type-1)%2 + 1)
		end

		if (button(x_p.x,x_p.y,30,30) or x_p.drag) and not f_m and not menu.w.sl.n and not menu.o.sl.n then
			ins = false
			if x_p.drag then
				rectb(x_p.x,x_p.y,30,30,13)
			else
				rectb(x_p.x,x_p.y,30,30,7)
			end
			if sc1 then x_p.type = (x_p.type+1)%5 end --click
			if tm1==2 then --drag (init)
				x_p.drag = true
				x_p.mx = mx - x_p.x
				x_p.my = my - x_p.y
			elseif tm1>2 then --drag (update)
				x_p.x = mx - x_p.mx
				x_p.y = my - x_p.my

				x_p.x = clip_val(x_p.x, 0, 210)
				x_p.y = clip_val(x_p.y, 7, 106)
			else
				x_p.drag = false
			end
			top_text = "left click to change ["..x_p.type.."], drag to move"
		end
		--right menu
		if menu.open then
			-- walls menu
			if menu.type==1 then
				rect(162,7,78,68,0)
				if f_m then vbank(0) end

				if button(162,7,78,68,false) then ins = false end

				print("Walls: "..menu.w.sel.."/"..#walls,164,9,7,false,1,true)
				print("Add",220,9,4)
				if button(218,8,21,7) then
					print("Add",220,9,7)
					top_text = "Add a new wall"
					if clp1 then
						walls[#walls+1] = {0,0,0,1,3,1,false,nil,nil,nil}
						menu.w.sel = #walls
						upd_walls()
					end
				end


				if menu.w.sel~=0 then
					if btnp(1,30,2) or btnp(2,30,2) then menu.w.sel = max(1, menu.w.sel-1) end
					if btnp(0,30,2) or btnp(3,30,2) then menu.w.sel = min(#walls, menu.w.sel+1) end

					local wall = walls[menu.w.sel]
					print("X:",164,19,11)
					print("Y:",164,27,14)
					print("Z:",164,35,9 )
					print("type:"  ,164,43,7)
					print("Normal:",164,51,7)
					print("Angle:" ,164,59,7)
					--
					local sl = menu.w.sl
					-- X Y Z
					local ind = {1,2,3,6,8,9,10}
					local min_max={{0,10},{0,5},{0,10},{1,17},{0,10},{0,5},{0,10}}
					min_max[wall[4]  ][2] = min_max[wall[4]  ][2]+1
					min_max[wall[4]+4][2] = min_max[wall[4]+4][2]+1
					if not wall[7] then
						for i = 1,3 do
							rectb(203,9+i*8,17,9,15)
							print_mid(wall[ind[i]],212,11+i*8,7)
							if button(204,10+i*8,15,7) then
								if clp1 then
									sl.n = true
									sl.id = i
									sl.val = wall[ind[i]]
									sl.val_2 = 0
									sl.t = 0
									mx = 0
									poke(0x7FC3F,1,1)
								end
							end
						end
					else
						for i = 1,3 do
							rectb(195,9+i*8,17,9,15)
							rectb(211,9+i*8,17,9,15)
							print_mid(wall[ind[i]],204,11+i*8,7)
							print_mid(wall[ind[i]+7],220,11+i*8,7)
							if button(196,10+i*8,15,7) then
								if clp1 then
									sl.n = true
									sl.id = i
									sl.val = wall[ind[i]]
									sl.val_2 = 0
									sl.t = 0
									mx = 0
									poke(0x7FC3F,1,1)
								end
							elseif button(212,10+i*8,15,7) then
							if clp1 then
								sl.n = true
								sl.id = i+4
								sl.val = wall[ind[i]+7]
								sl.val_2 = 0
								sl.t = 0
								mx = 0
								poke(0x7FC3F,1,1)
							end

							end
						end
					end
					
					--wall type
					rectb(203,41,17,9,15)
					print_mid(wall[ind[4]],212,43,7)
					if button(204,42,15,7) then
						if clp1 then
							sl.n = true
							sl.id = 4
							sl.val = wall[ind[4]]
							sl.val_2 = 0
							sl.t = 0
							mx = 0
							poke(0x7FC3F,1,1)
						end
					end
					--
					if sl.n then
						if cl1 then
							sl.t = sl.t + 1
							if sl.t>2 then
								sl.val_2 = sl.val_2 + mx
								if mx ~=0 then
									upd_walls()
								end
								wall[ind[sl.id]] = sl.val + sl.val_2//30


								if wall[ind[sl.id]]>min_max[sl.id][2] then
									wall[ind[sl.id]]=min_max[sl.id][2]
									sl.val_2 = 0
									sl.val = wall[ind[sl.id]]
								elseif wall[ind[sl.id]]<min_max[sl.id][1] then
									wall[ind[sl.id]]=min_max[sl.id][1]
									sl.val_2 = 0
									sl.val = wall[ind[sl.id]]
								end
							end
						elseif not cl1 then
							sl.t = 0
							show_cursor()
							sl.n = false
						end
					end
					--
					if f_m then
						spr(447 + wall[5],210,51,15)
						spr(431 + wall[4],210,59,15)
					else
						for vb = 0,1 do
							vbank(vb)
							spr(447 + wall[5],210,51,15)
							spr(431 + wall[4],210,59,15)
						end
					end
					--normal
					if button(210,51,5,5) then
						local text={
							"Only the front side is displayed",
							"Only the back side is displayed",
							"Both back side is displayed",
						}
						top_text = text[wall[5]]
						if clp1 then
							wall[5] = wall[5]%3 + 1
							upd_walls()
						end
					end

					--rotation
					if button(210,59,5,5) then
						local text={
							"Affects the rotation | YZ [wall]",
							"Affects the rotation | XZ [floor]",
							"Affects the rotation | XY [wall]",
						}
						top_text = text[wall[4]]
						if clp1 then
							wall[4] = wall[4]%3 + 1
							upd_walls()
						end
					end
					--stack wall button
					if f_m then
						if wall[7] then
							spr(437,210,7,15)
						else
							spr(453,210,7,15)
						end
					else
						for vb = 0,1 do
							vbank(vb)
							if wall[7] then
								spr(437,210,7,15)
							else
								spr(453,210,7,15)
							end
						end
					end

					if button(210,7,7,7) then
						top_text = "Allows you to add or edit multiple walls"
						if clp1 then
							wall[7] = not wall[7]

							if not wall[8] then
								wall[8 ] = wall[1]
								wall[9 ] = wall[2]
								wall[10] = wall[3]
							end
						end

						upd_walls()
					end
					--delete button
					print("Delete",203,67,13)
					if button(203,67,35,5) then
						print("Delete",203,67,7)
						top_text = "Delete the current wall"
						if clp1 then
							table.remove(walls, menu.w.sel)
							menu.w.sel = menu.w.sel - 1
							upd_walls()
						end
					end

					--clone button
					print("Clone",164,67,11)
					if button(164,67,29,5) then
						print("Clone",164,67,7)
						top_text = "Clone the current wall"
						if clp1 then
							walls[#walls+1] = {wall[1],wall[2],wall[3],wall[4],wall[5],wall[6],wall[7],wall[8],wall[9],wall[10]}
							menu.w.sel = #walls
							upd_walls()
						end
					end

					--X Y Z drager
					if false then -- it will be completed in the future
						vbank(1)
						local v_id = wall[1]+ wall[2]*world_size[3]+ wall[3]*world_size[4]+1

						local xp, yp = unitic.poly.v[v_id][1],unitic.poly.v[v_id][2]

						local distance = math.sqrt((wall[1]*96 - cam.x)^2 + (wall[2]*128 - cam.y)^2 + (wall[3]*96 - cam.z)^2)

						local xyz = xyz_pointer(xp-15,yp-15,1,unitic.fov*85/distance)

						--find nearest ray
						local function distance_to_ray(vx, vy, x, y)
							--normalization
							local vec_len = math.sqrt(vx * vx + vy * vy)
							vx = vx / vec_len
							vy = vy / vec_len


							--finding the projection of the point
							local dot_product = x * vx + y * vy

							local proj_x = dot_product * vx
							local proj_y = dot_product * vy

							if (vx>0 and proj_x<0) or (vx<0 and proj_x>0) then proj_x = 0 end
							if (vy>0 and proj_y<0) or (vy<0 and proj_y>0) then proj_y = 0 end


							--ray length
							local len = math.sqrt(proj_x * proj_x + proj_y * proj_y)

							-- distance from point to projection
							local dist = math.sqrt((proj_x - x)^2 + (proj_y - y)^2)

							return len, dist, proj_x, proj_y
						end

						local nearest = {
							i = -1,
							len = math.huge,
							dist = math.huge,
							proj_x = nil,
							proj_y = nil,
						}


						for i = 1, 3 do
							local len,dist, proj_x, proj_y = distance_to_ray(xyz[i][1]-xp,xyz[i][2]-yp,mx-xp, my-yp)

							if dist < nearest.dist then
								nearest.len = len
								nearest.dist = dist
								nearest.proj_x = proj_x
								nearest.proj_y = proj_y
								nearest.i = i
							end
						end

						if nearest.dist < 3 and nearest.len < unitic.fov*85/distance then
							line(xp,yp, xyz[nearest.i][1], xyz[nearest.i][2],12)
							cid = 1
						end
					end
				else
					print([[Click "Add" to]],165,29,4)
					print([[add a wall]],172,36,4)
				end
			end
			-- objects menu --
			if menu.type==2 then
				local tab = menu.o.tab
				local objs = objects[tab]
				rect(162,7,78,68,0)
				if f_m then vbank(0) end

				if button(162,7,78,68,false) then ins = false end
				
				rectb(155+menu.o.tab*9,7,9,9,14)

				for i=1,#objects_data.names do
					spr(402+i,156+i*9,8,15)
					if button(155+i*9,7,9,9) then
						rectb(155+i*9,7,9,9,7)
						top_text = "["..i.."] "..objects_data.names[i].."s tab"
						if clp1 then menu.o.tab = i end
					end

					if keyp(27+i) then menu.o.tab = i end
				end

				if menu.o.tab<7 then
					menu.o.sel[tab] = min(menu.o.sel[tab], #objects[tab])
					if #objects[tab] > 0 then menu.o.sel[tab] = max(menu.o.sel[tab],1) end

					print("Objects: "..menu.o.sel[tab].."/"..#objects[tab],164,18,7,false,1,true)

					print("Add",220,18,4)
					if button(218,17,21,7) then
						print("Add",220,18,7)
						top_text = "Add a new "..objects_data.names[tab]
						if clp1 then
							objs[#objs+1] = {48,64,48,objects_data.types[tab][1], nil}
							menu.o.sel[tab] = #objs
							upd_objs()
						end
					end

					if #objs~=0 then
						if btnp(1,30,2) or btnp(2,30,2) then menu.o.sel[tab] = max(1, menu.o.sel[tab]-1) end
						if btnp(0,30,2) or btnp(3,30,2) then menu.o.sel[tab] = min(#objs, menu.o.sel[tab]+1) end
						local obj = objs[menu.o.sel[tab]] --current object
						local sl = menu.o.sl --slider
						--type
						print("type: "..obj[4],176,25,7,false,1,true)
						if f_m then
							if menu.o.magnet then --magnet button
								spr(451,164,25,15)
							else
								spr(435,164,25,15)
							end
							if tab==1 then spr(418+obj[4],226,25,15) end --change skin button
						else
							
							for vb = 0,1 do
								vbank(vb)
								if menu.o.magnet then --magnet button
									spr(451,164,25,15)
								else
									spr(435,164,25,15)
								end
								if tab==1 then spr(418+obj[4],226,25,15) end --change skin button
							end
						end
						--magnet button
						if button(164,25,6,7) then
							top_text = "Alignment of coordinates on the grid"
							if clp1 then menu.o.magnet = not menu.o.magnet end
						end
						--change skin button
						if tab==1 and button(226,25,7,7) then
							top_text = "Change the object's skin"
							if clp1 then
								obj[4] = obj[4] % 2 + 1
								upd_objs()
							end
						end
						--rotate buttons
						if tab>2 and tab~=4 then
							for vb = 0,1 do
								vbank(vb)
								spr(436,231,25,15)
							end
							if button(231,25,8,8) and clp1 then
								obj[4] = (obj[4] - objects_data.types[tab][1] + 1)%4 + objects_data.types[tab][1]
								upd_objs()
							end
						end
						--X Y Z
						print("X:",164,39,11)
						print("Y:",164,47,14)
						print("Z:",164,55,9 )
						for i = 1,3 do
							rectb(198,29+i*8,27,9,15)
							print_mid(obj[i],212,31+i*8,7)
							if button(199,30+i*8,25,7) then
								if clp1 then
									sl.n = true
									sl.id = i
									sl.val = obj[i]
									sl.val_2 = 0
									sl.t = 0
									mx = 0
									poke(0x7FC3F,1,1)
								end
							end
						end
						--slider
						if sl.n then
							if cl1 then
								sl.t = sl.t + 1
								if sl.t>2 then
									if key(64) then
										sl.val_2 = sl.val_2 + mx / 30
									else
										sl.val_2 = sl.val_2 + mx
									end
									if mx ~=0 then
										upd_objs()
									end
									obj[sl.id] = sl.val + F(sl.val_2)
									if menu.o.magnet then
										local step = objects_data.m_step[tab][sl.id]
										obj[sl.id] = obj[sl.id] // step * step
									end
								end
							elseif not cl1 then
								sl.t = 0
								show_cursor()
								sl.n = false
							end
						end
						--Coordinates limit
						obj[1] = clip_val(obj[1], -1520, 2575)
						obj[2] = clip_val(obj[2], -116 , 907 )
						obj[3] = clip_val(obj[3], -1520, 2575)
						--delete button
						print("Delete",203,67,13)
						if button(203,67,35,5) then
							print("Delete",203,67,7)
							top_text = "Delete the current object"
							if clp1 then
								table.remove(objs, menu.o.sel[tab])
								menu.o.sel[tab] = menu.o.sel[tab] - 1
								upd_objs()
							end
						end

					else
						print([[Click "Add" to]],165,29+7,4)
						print([[add a object]],167,36+7,4)
					end
				end
			end

		end
		--mouse selection
			menu.w.m_sel = -1
			menu.o.m_sel = -1
			if (ins or cl2) then
			  local x1 = plr.x
			  local y1 = plr.y
			  local z1 = plr.z
			  
			  local x2 = -(mx - 120) / unitic.fov
			  local y2 = -(my - 68 ) / unitic.fov

			  if cl2 then x2,y2 = 0,0 end
			  local z2 = -1

			  local a1=x2
			  local b1=y2
			  local c1=z2
			  
			  local b2=b1*math.cos(-cam.tx)-c1*math.sin(-cam.tx)
			  local c2=b1*math.sin(-cam.tx)+c1*math.cos(-cam.tx)
			  local a2=a1
			  
			  local c3=c2*math.cos(cam.ty)-a2*math.sin(cam.ty)
			  local a3=c2*math.sin(cam.ty)+a2*math.cos(cam.ty)
			  local b3=b2

				x2 = a3
				y2 = b3
				z2 = c3
				if menu.type == 1 then
					local ray_params = {
						portals = false,
						walls = {true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true},
						floors = {true,true,true,true,true,true,true,true,true,true},
						objs = {}
					}
					local hit = raycast(x1,y1,z1,x2,y2,z2,1/0,ray_params)
					if hit then
						menu.w.m_sel = hit.tile[3]
						cid = 1
						if sc1 then menu.w.sel = menu.w.m_sel end
					end
				else
					local ray_params = {
						portals = false,
						walls = {},
						floors = {},
						objs = {"c","cd","b","t","fb","d"}
					}
					local hit = raycast(x1,y1,z1,x2,y2,z2,1/0,ray_params)
					if hit then
						cid = 1
						local obj_type = hit.obj.type
						local obj_id   = hit.obj.id

						local obj_tab = nil
						for i = 1, 6 do
							for i2 = 1, #objects_data.types[i] do
								if obj_type == objects_data.types[i][i2] then obj_tab = i break end
							end
						end

						menu.o.m_sel = obj_id
						menu.o.m_tab = obj_tab
						if sc1 then
							menu.o.tab = obj_tab
							menu.o.sel[obj_tab] = obj_id
						end
					end
				end
		  end
		--top debug panel (2)
		print(top_text,1,1,7)
	end
	------------------
	--- end ----------
	------------------
	--cursor id
	vbank(0)
	if fix_mouse then
		poke(0x3FFB, 0)
		fix_mouse = false
	else
		poke(0x3FFB, 128 + cid)
	end
	--fps (2)
	do
		avf[t%60]=t2
		t2 = time() - t1
		fr = {0,math.huge,0}
		for i=1,#avf do
			fr[1]=fr[1]+avf[i]
			if avf[i]<fr[2] then fr[2]=avf[i] end
			if avf[i]>fr[3] then fr[3]=avf[i] end
		end
		fr[1]=fr[1]/#avf
	end
end

function BDR(scn_y) scn_y=scn_y-4
	vbank(0)
	if state=="pause" or state=="clear confirm" then
		vbank(1)poke(0x03FF9,0)respal()vbank(0)poke(0x03FF9,0)
		upd_buttons_bdr(scn_y, function()respal()darkpal(max(1-p.t/30,0.4)) end)
	end
	if state=="edit" then
	end
end
