Overview
Comment: | Complete implementation of (Order) block (mostly untested so far) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
602616bb9177bd90a0b18ce3e7475c24 |
User & Date: | user on 2021-10-14 01:14:52 |
Other Links: | manifest | tags |
Context
2021-10-15
| ||
06:47 | Mention the UTI for Free Hero Mesh and improve code page documentation. (No changes to the program code.) check-in: a27d50ac26 user: user tags: trunk | |
2021-10-14
| ||
01:14 | Complete implementation of (Order) block (mostly untested so far) check-in: 602616bb91 user: user tags: trunk | |
2021-10-10
| ||
00:08 | More working in sound implementation (still incomplete, and some details are subject to being changed in future) check-in: 9692a28768 user: user tags: trunk | |
Changes
Modified TODO from [3998dd2b71] to [1a3fd7edc4].
︙ | ︙ | |||
8 9 10 11 12 13 14 | * 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) | < > > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | * 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 * Level index editor * Table of contents for levels * Can define your own columns * User can write SQL queries on them * Deal better with allowing to skip past corrupted levels * Picture editor/loading * Allowing more altimages * Spare page (for temporary use while editing) * Batch insert multiple dependent image lumps * Puzzle set catalog format (using with internet; a separate program) * Inventory/replay hybrid view * Bookmarks * Message trace menu to enable/disable * Bugs * Figure out why the $SeekerCloser class doesn't seem to work properly * Level 232 of SUPERHRO puzzle set (the Lava shouldn't expand? why?) * Animation stopping unexpectedly (until a key is pushed) * Display solution comments/timestamp * VCR mode * Command-line switch for batch import/export levels * SQL * Implement the GROUP column in the CLASSES table * Allow multiple SQL statements in one binding * Large fonts (width 8 or 16, height 8-32) * 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 (implemented) * Optional hypertext help * Compressed class definitions (?) * Option to auto display level titles * Testing * Bizarro world * Deferred movement * Sweep, SweepEx, HitMe * Overriding order of execution |
Modified class.c from [459caf781d] to [f768010252].
︙ | ︙ | |||
2167 2168 2169 2170 2171 2172 2173 | } if(!norders) ParseError("Empty (Order) block\n"); orders=realloc(orders,ptr*sizeof(Uint16))?:orders; } static void set_class_orders(void) { int i,j,k; | | | 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 | } if(!norders) ParseError("Empty (Order) block\n"); orders=realloc(orders,ptr*sizeof(Uint16))?:orders; } static void set_class_orders(void) { int i,j,k; for(i=1;i<undef_class;i++) if(classes[i] && (classes[i]->nmsg || classes[0]->nmsg) || !(classes[i]->cflags&(CF_GROUP|CF_NOCLASS2))) { for(j=1;j<norders;j++) { k=orders[orders[j]]; switch(k) { case 0x1000 ... 0x101F: if(classes[i]->misc4&(1UL<<(k&0x1F))) goto found; break; case 0x1020 ... 0x103F: if(classes[i]->misc5&(1UL<<(k&0x1F))) goto found; break; case 0x1040 ... 0x105F: if(classes[i]->misc6&(1UL<<(k&0x1F))) goto found; break; case 0x1060 ... 0x107F: if(classes[i]->misc7&(1UL<<(k&0x1F))) goto found; break; |
︙ | ︙ |
Modified class.doc from [985a0314d5] to [22956477d6].
︙ | ︙ | |||
285 286 287 288 289 290 291 | 32 flags can be defined in this way. (Misc7 <userflags...>) Define user flags as Misc7 bits; the first defined flag is bit0. Up to 32 flags can be defined in this way. (Order <orders...>) | | > > | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | 32 flags can be defined in this way. (Misc7 <userflags...>) Define user flags as Misc7 bits; the first defined flag is bit0. Up to 32 flags can be defined in this way. (Order <orders...>) See the section below about order of execution. Normally, order of execution (for broadcasts and some other things) is in the reverse order of creation; the (Order) block allows you to override this order. (Synchronize <slot> <length> <speed>) Define an animation slot for synchronized animation. The slot number can be 0 to 7, the length is the number of images in the sequence, and the speed is the number of centiseconds between frames. (Volume <number>) |
︙ | ︙ | |||
2468 2469 2470 2471 2472 2473 2474 | Trace Used for debugging. === Order of execution === | < < < < | 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 | Trace Used for debugging. === Order of execution === You can specify the order of execution of objects by class by a global (Order) block. Inside of this block is a list of sub-lists; each sub-list is delimited by parentheses. Each sub-list starts with a flag name, which may be a user flag, or Input, or Player. This matches only classes that have that flag (changing that flag at run time has no effect on order of execution). The remaining |
︙ | ︙ | |||
2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 | the values is not a number, then it is an error. The order of execution is then first all objects not listed in the (Order) block, and then for each sub-list in the (Order) block, the objects that meet that criteria, in that order. (If it meets multiple criteria, only the first one that meets that criteria is used.) === Compatibility === Compatible objects have the following differences from the default: * VisualOnly implies Stealthy. | > > > > > | 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 | the values is not a number, then it is an error. The order of execution is then first all objects not listed in the (Order) block, and then for each sub-list in the (Order) block, the objects that meet that criteria, in that order. (If it meets multiple criteria, only the first one that meets that criteria is used.) Note: If a value used for the criteria changes after the INIT or CREATE message of that object returns, then it can result in an unstable (but still fully deterministic) order when new objects are created. For this reason, you should only use criteria based on values which don't change. === Compatibility === Compatible objects have the following differences from the default: * VisualOnly implies Stealthy. |
︙ | ︙ |
Modified exec.c from [85a769bf13] to [c5fcde1ccc].
︙ | ︙ | |||
664 665 666 667 668 669 670 671 672 673 674 675 676 677 | destroy(n,e[i],3); } } if(obj_layer_at(b,x,y)!=VOIDLINK) r|=0x01; } return r; } static Uint32 create(Uint32 from,Uint16 c,Uint32 x,Uint32 y,Uint32 im,Uint32 d) { Uint32 m,n; int i,xx,yy; Object*o; Object*p; Value v; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 | destroy(n,e[i],3); } } if(obj_layer_at(b,x,y)!=VOIDLINK) r|=0x01; } return r; } static void set_order(Uint32 obj) { // To avoid confusing order of execution at the wrong time, // calling this function is limited to only certain times. Object*o=objects[obj]; Uint8 ord=classes[objects[obj]->class]->order; Uint8 u; Sint32 v0,v1; Uint16 p=orders[ord]+1; Uint32 n=firstobj; for(;;) { if(n==obj || n==VOIDLINK) goto notfound; u=classes[objects[n]->class]->order; if(u<ord) goto found; if(u==ord) { criteria: switch(orders[p]) { case OP_RET: goto found; case OP_DENSITY: v0=o->density; v1=objects[n]->density; goto compare; case OP_DENSITY_C: v1=o->density; v0=objects[n]->density; goto compare; case OP_IMAGE: v0=o->image; v1=objects[n]->image; goto compare; case OP_IMAGE_C: v1=o->image; v0=objects[n]->image; goto compare; case OP_MISC1: if(o->misc1.t || objects[n]->misc1.t) Throw("Type mismatch in order criteria"); v0=o->misc1.s; v1=objects[n]->misc1.s; goto compare; case OP_MISC1_C: if(o->misc1.t || objects[n]->misc1.t) Throw("Type mismatch in order criteria"); v1=o->misc1.s; v0=objects[n]->misc1.s; goto compare; case OP_MISC2: if(o->misc2.t || objects[n]->misc2.t) Throw("Type mismatch in order criteria"); v0=o->misc2.s; v1=objects[n]->misc2.s; goto compare; case OP_MISC2_C: if(o->misc2.t || objects[n]->misc2.t) Throw("Type mismatch in order criteria"); v1=o->misc2.s; v0=objects[n]->misc2.s; goto compare; case OP_MISC3: if(o->misc3.t || objects[n]->misc3.t) Throw("Type mismatch in order criteria"); v0=o->misc3.s; v1=objects[n]->misc3.s; goto compare; case OP_MISC3_C: if(o->misc3.t || objects[n]->misc3.t) Throw("Type mismatch in order criteria"); v1=o->misc3.s; v0=objects[n]->misc3.s; goto compare; case OP_MISC4: if(o->misc4.t || objects[n]->misc4.t) Throw("Type mismatch in order criteria"); v0=o->misc4.s; v1=objects[n]->misc4.s; goto compare; case OP_MISC4_C: if(o->misc4.t || objects[n]->misc4.t) Throw("Type mismatch in order criteria"); v1=o->misc4.s; v0=objects[n]->misc4.s; goto compare; case OP_MISC5: if(o->misc5.t || objects[n]->misc5.t) Throw("Type mismatch in order criteria"); v0=o->misc5.s; v1=objects[n]->misc5.s; goto compare; case OP_MISC5_C: if(o->misc5.t || objects[n]->misc5.t) Throw("Type mismatch in order criteria"); v1=o->misc5.s; v0=objects[n]->misc5.s; goto compare; case OP_MISC6: if(o->misc6.t || objects[n]->misc6.t) Throw("Type mismatch in order criteria"); v0=o->misc6.s; v1=objects[n]->misc6.s; goto compare; case OP_MISC6_C: if(o->misc6.t || objects[n]->misc6.t) Throw("Type mismatch in order criteria"); v1=o->misc6.s; v0=objects[n]->misc6.s; goto compare; case OP_MISC7: if(o->misc7.t || objects[n]->misc7.t) Throw("Type mismatch in order criteria"); v0=o->misc7.s; v1=objects[n]->misc7.s; goto compare; case OP_MISC7_C: if(o->misc7.t || objects[n]->misc7.t) Throw("Type mismatch in order criteria"); v1=o->misc7.s; v0=objects[n]->misc7.s; goto compare; case OP_TEMPERATURE: v0=o->temperature; v1=objects[n]->temperature; goto compare; case OP_TEMPERATURE_C: v1=o->temperature; v0=objects[n]->temperature; goto compare; case OP_XLOC: v0=o->x; v1=objects[n]->x; goto compare; case OP_XLOC_C: v1=o->x; v0=objects[n]->x; goto compare; case OP_YLOC: v0=o->y; v1=objects[n]->y; goto compare; case OP_YLOC_C: v1=o->y; v0=objects[n]->y; goto compare; compare: if(v0==v1) { p++; goto criteria; } if(v0>v1) goto found; break; default: fatal("Internal confusion: Invalid order criteria (%d)\n",orders[p]); } } n=objects[n]->next; } found: // Now it has been found; insert this object previous to the found object, removing from its existing slot. // (Objects are executed in reverse order, so previous in the linked list means executed next) if(firstobj==obj) firstobj=o->next; if(lastobj==obj) lastobj=o->prev; if(o->prev!=VOIDLINK) objects[o->prev]->next=o->next; if(o->next!=VOIDLINK) objects[o->next]->prev=o->prev; o->prev=objects[n]->prev; o->next=n; objects[n]->prev=obj; if(o->prev==VOIDLINK) firstobj=obj; if(objects[n]->next==VOIDLINK) lastobj=n; notfound: objects[obj]->oflags|=OF_ORDERED; } static Uint32 create(Uint32 from,Uint16 c,Uint32 x,Uint32 y,Uint32 im,Uint32 d) { Uint32 m,n; int i,xx,yy; Object*o; Object*p; Value v; |
︙ | ︙ | |||
699 700 701 702 703 704 705 706 707 708 709 710 711 712 | while(m!=VOIDLINK) { p=objects[m]; if(p->arrivals&(1<<i)) if(m!=n) send_message(n,m,MSG_CREATED,NVALUE(o->x),NVALUE(o->y),v); m=p->up; } } if(o->oflags&OF_DESTROYED) return VOIDLINK; m=objects[n]->up; if(m!=VOIDLINK) { v=send_message(VOIDLINK,n,MSG_SUNK,NVALUE(0),NVALUE(0),v); while(m!=VOIDLINK) { send_message(n,m,MSG_FLOATED,NVALUE(0),NVALUE(0),v); m=objects[m]->up; } | > | 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 | while(m!=VOIDLINK) { p=objects[m]; if(p->arrivals&(1<<i)) if(m!=n) send_message(n,m,MSG_CREATED,NVALUE(o->x),NVALUE(o->y),v); m=p->up; } } if(o->oflags&OF_DESTROYED) return VOIDLINK; if(classes[objects[n]->class]->order) set_order(n); m=objects[n]->up; if(m!=VOIDLINK) { v=send_message(VOIDLINK,n,MSG_SUNK,NVALUE(0),NVALUE(0),v); while(m!=VOIDLINK) { send_message(n,m,MSG_FLOATED,NVALUE(0),NVALUE(0),v); m=objects[m]->up; } |
︙ | ︙ | |||
3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 | if(generation_number<=TY_MAXTYPE) return "Too many generations of objects"; if(firstobj==VOIDLINK) return "Game cannot continue with no objects"; // Finished return 0; } const char*init_level(void) { if(setjmp(my_env)) return my_error; clear_inventory(); if(main_options['t']) { printf("[Level %d restarted]\n",level_id); if(!traced_obj.t) { const char*s; optionquery[1]=Q_traceObject; | > | 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 | if(generation_number<=TY_MAXTYPE) return "Too many generations of objects"; if(firstobj==VOIDLINK) return "Game cannot continue with no objects"; // Finished return 0; } const char*init_level(void) { Uint32 n; if(setjmp(my_env)) return my_error; clear_inventory(); if(main_options['t']) { printf("[Level %d restarted]\n",level_id); if(!traced_obj.t) { const char*s; optionquery[1]=Q_traceObject; |
︙ | ︙ | |||
3173 3174 3175 3176 3177 3178 3179 | changed=0; key_ignored=0; all_flushed=0; lastimage_processing=0; vstackptr=0; move_number=0; current_key=0; | > > | > > > | 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 | changed=0; key_ignored=0; all_flushed=0; lastimage_processing=0; vstackptr=0; move_number=0; current_key=0; n=lastobj; while(n!=VOIDLINK && !(objects[n]->oflags&OF_ORDERED)) { send_message(VOIDLINK,n,MSG_INIT,NVALUE(0),NVALUE(0),NVALUE(0)); if(classes[objects[n]->class]->order && !(objects[n]->oflags&OF_DESTROYED)) set_order(n); n=objects[n]->prev; } broadcast(VOIDLINK,0,MSG_POSTINIT,NVALUE(0),NVALUE(0),NVALUE(0),0); if(gameover) return 0; return execute_turn(0); } |
Modified heromesh.h from [66fec90ead] to [9e46039699].
︙ | ︙ | |||
140 141 142 143 144 145 146 147 148 149 150 151 152 153 | #define OF_MOVED 0x0040 #define OF_DONE 0x0080 #define OF_KEYCLEARED 0x0100 #define OF_DESTROYED 0x0200 #define OF_BIZARRO 0x0400 #define OF_MOVED2 0x0800 #define OF_MOVING 0x1000 typedef struct { const char*name; const char*edithelp; // not present if CF_GROUP const char*gamehelp; // not present if CF_GROUP Uint16*codes; Uint16*messages; // use 0xFFFF if no such message block | > | 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | #define OF_MOVED 0x0040 #define OF_DONE 0x0080 #define OF_KEYCLEARED 0x0100 #define OF_DESTROYED 0x0200 #define OF_BIZARRO 0x0400 #define OF_MOVED2 0x0800 #define OF_MOVING 0x1000 #define OF_ORDERED 0x2000 typedef struct { const char*name; const char*edithelp; // not present if CF_GROUP const char*gamehelp; // not present if CF_GROUP Uint16*codes; Uint16*messages; // use 0xFFFF if no such message block |
︙ | ︙ |