Overview
Comment: | Implement bizarro editing. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
6b326d94b847cd1021057334acb3aef6 |
User & Date: | user on 2021-09-12 00:57:03 |
Other Links: | manifest | tags |
Context
2021-09-12
| ||
04:37 | Add possibility to adjust replay speed at run time. check-in: 1d89b3ab66 user: user tags: trunk | |
00:57 | Implement bizarro editing. check-in: 6b326d94b8 user: user tags: trunk | |
2021-09-11
| ||
07:00 | Implement much more of bizarro world (currently untested, and not implemented in level editor yet). check-in: 2a3e5126fe user: user tags: trunk | |
Changes
Modified TODO from [9de01445bc] to [d20541f055].
1 2 3 4 5 6 7 8 9 | * Sound effects * Wave sounds * Standard sounds * User sounds * Compressed wave sounds (?) * MML sounds * Numeric sounds (?) * Game engine features * Multiple connected objects moving as a unit | < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | * Sound effects * Wave sounds * Standard sounds * User sounds * Compressed wave sounds (?) * MML sounds * Numeric sounds (?) * Game engine features * Multiple connected objects moving as a unit * String data * A ,PopUp command to use a popup with arguments starting from a mark * "Goto message" instruction (?) * Returning a class from COLLIDE/COLLIDEBY to transform * Coordinate input (may be suitable for some kind of games) * Editor * Mouse dragging |
︙ | ︙ | |||
44 45 46 47 48 49 50 | * Branching replay recording * Slow movement displaying state between triggers * Warning if file changed when uncommited data exists in the cache database * Composite puzzle set format (in a single file; read-only) * Optional hypertext help * Compressed class definitions (?) * Option to auto display level titles | > > > | 42 43 44 45 46 47 48 49 50 51 | * Branching replay recording * Slow movement displaying state between triggers * Warning if file changed when uncommited data exists in the cache database * Composite puzzle set format (in a single file; read-only) * Optional hypertext help * Compressed class definitions (?) * Option to auto display level titles * Testing * Bizarro world * Deferred movement |
Modified bindings.doc from [18a5b1ed51] to [f5d84d82bf].
︙ | ︙ | |||
138 139 140 141 142 143 144 145 146 147 148 149 150 151 | '^s' Display the list of level strings. '^u' <location> Add an object with the current MRU values to that location, even if there is already another object of the same class at that location. 'em' <object> Edit the Misc/Dir of an existing object. 'ex' <command> Export a level (given the operating system command to receive the exported data). See export.doc for details. | > > > | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | '^s' Display the list of level strings. '^u' <location> Add an object with the current MRU values to that location, even if there is already another object of the same class at that location. '^w' Swap the normal world with the bizarro world. 'em' <object> Edit the Misc/Dir of an existing object. 'ex' <command> Export a level (given the operating system command to receive the exported data). See export.doc for details. |
︙ | ︙ |
Modified default.heromeshrc from [77e855c5b3] to [a8c6aa6da8].
︙ | ︙ | |||
142 143 144 145 146 147 148 149 150 151 152 153 154 155 | ?.editKey.9: select 'mr',8; ?.editKey.up: select 'mR',-1; ?.editKey.down: select 'mR',+1; ?.editKey.C: select 'lc',:level_code where :level_code=cast(:level_code as int); ?.editKey.E: ^s ?.editKey.F: with n(n) as (select 65 union all select n+1 h from n where h<=64*pfheight()+65) select '^a',n from n; ?.editKey.R: select 're',substr(:resize,1,instr(:resize,'x')-1),substr(:resize,instr(:resize,'x')+1) where length(:resize); ?.editKey.ctrl.N: ^N ?.editKey.ctrl.P: ^P ?.editKey.ctrl.X: select 're',pfwidth(),pfheight(); ?.editKey.space: ^c ?.editKey.return: ^e ?.editKey.f1: select 'im',:Import_Level; ?.editKey.f2: select 'ex',:Export_Level; | > | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | ?.editKey.9: select 'mr',8; ?.editKey.up: select 'mR',-1; ?.editKey.down: select 'mR',+1; ?.editKey.C: select 'lc',:level_code where :level_code=cast(:level_code as int); ?.editKey.E: ^s ?.editKey.F: with n(n) as (select 65 union all select n+1 h from n where h<=64*pfheight()+65) select '^a',n from n; ?.editKey.R: select 're',substr(:resize,1,instr(:resize,'x')-1),substr(:resize,instr(:resize,'x')+1) where length(:resize); ?.editKey.W: ^w ?.editKey.ctrl.N: ^N ?.editKey.ctrl.P: ^P ?.editKey.ctrl.X: select 're',pfwidth(),pfheight(); ?.editKey.space: ^c ?.editKey.return: ^e ?.editKey.f1: select 'im',:Import_Level; ?.editKey.f2: select 'ex',:Export_Level; |
︙ | ︙ |
Modified edit.c from [3589f5cda0] to [10af50702a].
︙ | ︙ | |||
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | bit7-bit6 = How many (0=has Misc2 and Misc3, not Misc1) bit5-bit4 = Misc3 type bit3-bit2 = Misc2 type bit1-bit0 = Misc1 type * misc data (variable size) Store/use MRU slot 0 if any bits of 0x70 set in flag byte; slot 1 otherwise */ Uint8 x=0; Uint8 y=1; const Object*m[2]={0,0}; sqlite3_str*str=sqlite3_str_new(0); Uint32 n; long sz; char*data; int i; // Header if(level_changed) version_change(); level_changed=0; sqlite3_str_appendchar(str,1,level_version&255); sqlite3_str_appendchar(str,1,level_version>>8); sqlite3_str_appendchar(str,1,level_code&255); sqlite3_str_appendchar(str,1,level_code>>8); sqlite3_str_appendchar(str,1,pfwidth-1); sqlite3_str_appendchar(str,1,pfheight-1); if(level_title) sqlite3_str_appendall(str,level_title); sqlite3_str_appendchar(str,1,0); // Objects for(i=0;i<64*64;i++) { | > > | > > > > > > > > > | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | bit7-bit6 = How many (0=has Misc2 and Misc3, not Misc1) bit5-bit4 = Misc3 type bit3-bit2 = Misc2 type bit1-bit0 = Misc1 type * misc data (variable size) Store/use MRU slot 0 if any bits of 0x70 set in flag byte; slot 1 otherwise */ Uint32*p=playfield; Uint8 x=0; Uint8 y=1; const Object*m[2]={0,0}; sqlite3_str*str=sqlite3_str_new(0); Uint32 n; long sz; char*data; int i; // Header if(level_changed) version_change(); level_changed=0; sqlite3_str_appendchar(str,1,level_version&255); sqlite3_str_appendchar(str,1,level_version>>8); sqlite3_str_appendchar(str,1,level_code&255); sqlite3_str_appendchar(str,1,level_code>>8); sqlite3_str_appendchar(str,1,pfwidth-1); sqlite3_str_appendchar(str,1,pfheight-1); if(level_title) sqlite3_str_appendall(str,level_title); sqlite3_str_appendchar(str,1,0); // Objects again: for(i=0;i<64*64;i++) { n=p[i]; while(n!=VOIDLINK) { save_obj(str,objects[n],m,x,y); x=objects[n]->x; y=objects[n]->y; n=objects[n]->up; } } save_obj(str,0,m,x,y); if(p==playfield) { p=bizplayfield; for(i=0;i<64*64;i++) if(p[i]!=VOIDLINK) { sqlite3_str_appendchar(str,1,0xFE); x=0; y=1; goto again; } } sqlite3_str_appendchar(str,1,0xFF); // Level strings for(i=0;i<nlevelstrings;i++) { sqlite3_str_appendall(str,levelstrings[i]); sqlite3_str_appendchar(str,1,0); } // Done |
︙ | ︙ | |||
744 745 746 747 748 749 750 751 752 753 754 755 756 757 | n=objects[n]->up; } } generation_number_inc=0; n=objalloc(m->class); if(n==VOIDLINK) return; level_changed=1; objects[n]->x=x; objects[n]->y=y; objects[n]->image=m->img; objects[n]->dir=m->dir; objects[n]->misc1=m->misc1; objects[n]->misc2=m->misc2; objects[n]->misc3=m->misc3; | > | 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 | n=objects[n]->up; } } generation_number_inc=0; n=objalloc(m->class); if(n==VOIDLINK) return; level_changed=1; objects[n]->oflags&=~OF_BIZARRO; objects[n]->x=x; objects[n]->y=y; objects[n]->image=m->img; objects[n]->dir=m->dir; objects[n]->misc1=m->misc1; objects[n]->misc2=m->misc2; objects[n]->misc3=m->misc3; |
︙ | ︙ | |||
794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 | case TY_MESSAGE: fprintf(fp," %s%s",v.u<256?"":"#",v.u<256?standard_message_names[v.u]:messages[v.u-256]); case TY_LEVELSTRING: fprintf(fp," %%%u",(int)v.u); break; default: fprintf(fp," ???"); break; } } static void export_level(const char*cmd) { int i; Uint32 n; Object*o; FILE*fp; if(!cmd || !*cmd) return; fp=popen(cmd,"w"); if(!fp) { screen_message("Cannot open pipe"); return; } fprintf(fp,"; Free Hero Mesh exported level ID=%d ORD=%d\n",level_id,level_ord); fprint_esc(fp,'@',level_title); fprintf(fp,"C %d\nD %d %d\n",level_code,pfwidth,pfheight); for(i=0;i<64*64;i++) { | > > | > > > > > > > > > | 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 | case TY_MESSAGE: fprintf(fp," %s%s",v.u<256?"":"#",v.u<256?standard_message_names[v.u]:messages[v.u-256]); case TY_LEVELSTRING: fprintf(fp," %%%u",(int)v.u); break; default: fprintf(fp," ???"); break; } } static void export_level(const char*cmd) { Uint32*p=playfield; int i; Uint32 n; Object*o; FILE*fp; if(!cmd || !*cmd) return; fp=popen(cmd,"w"); if(!fp) { screen_message("Cannot open pipe"); return; } fprintf(fp,"; Free Hero Mesh exported level ID=%d ORD=%d\n",level_id,level_ord); fprint_esc(fp,'@',level_title); fprintf(fp,"C %d\nD %d %d\n",level_code,pfwidth,pfheight); again: for(i=0;i<64*64;i++) { n=p[i]; while(n!=VOIDLINK) { o=objects[n]; fprintf(fp,"%d %d $%s %d",o->x,o->y,classes[o->class]->name,o->image); fprint_misc(fp,o->misc1); fprint_misc(fp,o->misc2); fprint_misc(fp,o->misc3); fprintf(fp," %d\n",o->dir); n=o->up; } } if(p==playfield) { p=bizplayfield; for(i=0;i<64*64;i++) if(p[i]!=VOIDLINK) { fprintf(fp,"W\n"); goto again; } } else { fprintf(fp,"W\n"); } for(i=0;i<nlevelstrings;i++) fprint_esc(fp,'%',levelstrings[i]); pclose(fp); } static char*import_numbers(char*p,int*x,int*y) { if(!p) return 0; while(*p==' ' || *p=='\t') p++; |
︙ | ︙ | |||
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 | break; case 'V': p=import_numbers(p+1,&x,0); if(!p || *p) goto bad; level_version=x; level_changed=0; break; case '@': free(level_title); level_title=import_string(p+1); break; case '%': if(nlevelstrings>0x2000) { screen_message("Too many level strings"); | > > > > | 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 | break; case 'V': p=import_numbers(p+1,&x,0); if(!p || *p) goto bad; level_version=x; level_changed=0; break; case 'W': if(!d) goto missd; swap_world(); break; case '@': free(level_title); level_title=import_string(p+1); break; case '%': if(nlevelstrings>0x2000) { screen_message("Too many level strings"); |
︙ | ︙ | |||
1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 | return 0; case '^s': // String list/edit string_list(); return 0; case '^u': // Add object (allow duplicates) if(prev) return prev; add_object_at(number&63?:64,number/64?:64,mru+curmru,0); return 0; case '^N': // New level if(level_nindex>0xFFFE) return 0; new_level(); return 1; case '^P': // Play return -2; | > > > > | 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 | return 0; case '^s': // String list/edit string_list(); return 0; case '^u': // Add object (allow duplicates) if(prev) return prev; add_object_at(number&63?:64,number/64?:64,mru+curmru,0); return 0; case '^w': // Swap world swap_world(); level_changed=1; return 0; case '^N': // New level if(level_nindex>0xFFFE) return 0; new_level(); return 1; case '^P': // Play return -2; |
︙ | ︙ |
Modified export.doc from [c550d0d7d1] to [39ee704f6d].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | This document describes the level export format of Free Hero Mesh. You can use this format for the following purposes: * To copy a level in Free Hero Mesh, within the same puzzle set or from one puzzle set to another one. * To export a level, to be parsed by an external program. * To produce by an external program and then import into Free Hero Mesh. * To edit it in a text editor. Each line is one record, and is terminated by a line feed. Everything in this file is case-sensitive. === Types of records === | > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | This document describes the level export format of Free Hero Mesh. You can use this format for the following purposes: * To copy a level in Free Hero Mesh, within the same puzzle set or from one puzzle set to another one. * To export a level, to be parsed by an external program. * To produce by an external program and then import into Free Hero Mesh. * To edit it in a text editor. (In the first case, when duplicating the level within the same puzzle set, you can also just copy the .LVL lump. However, that will not work if you are copying between puzzle sets.) Each line is one record, and is terminated by a line feed. Everything in this file is case-sensitive. === Types of records === |
︙ | ︙ | |||
33 34 35 36 37 38 39 40 41 42 43 44 45 46 | line must come before any objects are listed, and is mandatory. V version This command never occurs in levels exported from Free Hero Mesh, although it can optionally occur in imported levels. If it is specified, then it sets the level version number. x y $class image misc1 misc2 misc3 dir Specify an object. Objects are listed starting from the top left corner, going right, and within each cell the objects are listed from bottom to top. Coordinates are one-based. The image is a number (0 for the first image), misc1 to misc3 are misc values (see below), and dir is also a number (0 for east, up to 7 for southeast). When the data is being imported, it will accept objects listed in any order, but when being | > > > > | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | line must come before any objects are listed, and is mandatory. V version This command never occurs in levels exported from Free Hero Mesh, although it can optionally occur in imported levels. If it is specified, then it sets the level version number. W After all objects in the normal world, use this command to start the objects in the bizarro world; you then need another W at the end. x y $class image misc1 misc2 misc3 dir Specify an object. Objects are listed starting from the top left corner, going right, and within each cell the objects are listed from bottom to top. Coordinates are one-based. The image is a number (0 for the first image), misc1 to misc3 are misc values (see below), and dir is also a number (0 for east, up to 7 for southeast). When the data is being imported, it will accept objects listed in any order, but when being |
︙ | ︙ |
Modified main.c from [66efb586aa] to [2fa2744cde].
︙ | ︙ | |||
234 235 236 237 238 239 240 | level_title=0; annihilate(); generation_number=TY_MAXTYPE+1; generation_number_inc=0; level_version=p[0]|(p[1]<<8); level_code=p[2]|(p[3]<<8); p+=4; | < | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | level_title=0; annihilate(); generation_number=TY_MAXTYPE+1; generation_number_inc=0; level_version=p[0]|(p[1]<<8); level_code=p[2]|(p[3]<<8); p+=4; pfwidth=(*p++&63)+1; pfheight=(*p++&63)+1; while(*p && p<end) p++; // skip text for now p++; // skip null terminator if(p>=end) goto bad1; level_title=strdup(buf+6); if(!level_title) fatal("Allocation failed\n"); |
︙ | ︙ | |||
265 266 267 268 269 270 271 | objects[o]->y=y; if(x>pfwidth) goto bad2; pflink(o); --n; } else { if(p>=end) goto bad1; z=*p++; | | | | | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | objects[o]->y=y; if(x>pfwidth) goto bad2; pflink(o); --n; } else { if(p>=end) goto bad1; z=*p++; if(z==0xFF) break; if(z==0xFE) { of^=OF_BIZARRO; goto restart; } if(z&0x20) x=*p++; if(z&0x10) y=*p++; if(z&0x40) x++; if(!x || !y || x>pfwidth || y>pfheight) goto bad2; n=z&0x70?0:1; |
︙ | ︙ |