Index: class.c ================================================================== --- class.c +++ class.c @@ -2227,11 +2227,11 @@ nxttok(); if(Tokenf(TF_MACRO|TF_COMMA|TF_EQUAL) || !Tokenf(TF_NAME)) ParseError("Unexpected token in (Order) block\n"); orders[++norders]=ptr; if(norders==beg) ParseError("Too many orders\n"); switch(tokenv) { - case OP_INPUT: case OP_PLAYER: case OP_CONTROL: + case OP_INPUT: case OP_PLAYER: case OP_CONTROL: case 0x4000 ... 0x7FFF: orders[ptr++]=tokenv; break; case OP_USERFLAG: tokenv=look_hash(glohash,HASH_SIZE,0x1000,0x10FF,0,"user flags"); if(!tokenv) ParseError("User flag ^%s not defined\n",tokenstr); @@ -2253,10 +2253,11 @@ case OP_TEMPERATURE: case OP_TEMPERATURE_C: case OP_DENSITY: case OP_DENSITY_C: case OP_XLOC: case OP_XLOC_C: case OP_YLOC: case OP_YLOC_C: case OP_IMAGE: case OP_IMAGE_C: + case 0xC000 ... 0xFFFF: orders[ptr++]=tokenv; break; default: ParseError("Unexpected token in (Order) block\n"); } } @@ -2266,11 +2267,11 @@ if(!norders) ParseError("Empty (Order) block\n"); orders=realloc(orders,ptr*sizeof(Uint16))?:orders; } static void set_class_orders(void) { - int i,j,k; + int i,j,k,m; if(main_options['C']) { for(j=1;j<=norders;j++) { printf("Order %d =",j); k=orders[j]; while(orders[k]!=OP_RET) printf(" %04X",orders[k++]); @@ -2284,10 +2285,18 @@ 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; case 0x1080 ... 0x1087: if(classes[i]->collisionLayers&(1L<<(k&0x07))) goto found; break; + case 0x4000 ... 0x7FFF: + if(i+0x4000==k) goto found; + m=i; + while(m && classes[m]->codes && classes[m]->codes[0]==OP_SUPER) { + if(classes[m]->codes[1]+0x4000==k) goto found; + m=classes[m]->codes[1]; + } + break; case OP_PLAYER: if(classes[i]->cflags&CF_PLAYER) goto found; break; case OP_INPUT: if(classes[i]->cflags&CF_INPUT) goto found; break; case OP_CONTROL: if(i==control_class) goto found; break; } continue; Index: class.doc ================================================================== --- class.doc +++ class.doc @@ -2779,11 +2779,14 @@ (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, or Control. This matches only classes that have that flag -(changing that flag at run time has no effect on order of execution). +(changing that flag at run time has no effect on order of execution). A +sub-list can also start with a class name, in which case only objects of +that class match; if it is an abstract class then any classes that inherit +from it (directly or indirectly) also match. The remaining elements are optional; if they are present, they are used to break ties. First, the second item breaks ties if there is one, and then if there is still a tie then the third item breaks ties, etc. These extra elements can be one of the following, with or without a comma: Misc1, @@ -2790,10 +2793,20 @@ Misc2, Misc3, Misc4, Misc5, Misc6, Misc7, Temperature, Density, Xloc, Yloc, Image. If there is no comma, they are lowest to highest, but a comma reverses the order to be highest to lowest instead. These values are treated as signed, and the values after INIT or CREATE message returns is used. If any of the values is not a number, then it is an error. + +Custom criteria are also possible. In this case, any of the items in the +list (other than the first one) can be a user-defined message name (but not +a built-in message). In this case, the message is sent to other objects that +match the first element of the current list to compare them. From is the +object that needs to be inserted into the list (which has just been created +or initialized), and Arg1 and Arg2 are the coordinates of that object. The +return value is negative or positive for the result of the comparison, or +zero if the result is a tie. State-changing effects are not allowed during +the processing of this message. 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.) Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -728,10 +728,11 @@ Uint8 ord=classes[o->class]->order; Uint8 u; Sint32 v0,v1; Uint16 p; Uint32 n=firstobj; + Value v; for(;;) { if(n==obj || n==VOIDLINK) goto notfound; u=classes[objects[n]->class]->order; if(uoflags&OF_ORDERED)) goto found; if(u==ord) { @@ -788,10 +789,18 @@ 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; + case 0xC000 ... 0xFFFF: // message + changed=0; + v=send_message(obj,n,(orders[p]&0x3FFF)+256,NVALUE(o->x),NVALUE(o->y),NVALUE(0)); + if(changed) Throw("State-changing is not allowed during ordering"); + changed=1; + if((o->oflags|objects[n]->oflags)&OF_DESTROYED) Throw("Destruction during ordering"); + if(v.t) Throw("Type mismatch in order criteria"); + v0=0; v1=v.s; goto compare; compare: if(v0==v1) { p++; goto criteria; } Index: internals.doc ================================================================== --- internals.doc +++ internals.doc @@ -100,10 +100,27 @@ remain the same between versions of Free Hero Mesh; they often change. Some of these numbers, including the OP_ constants, are also used during parsing; some of them occur only as tokens and not in the compiled P-code, and some only occur in the compiled P-code and not as tokens. + +Any class that inherits from another class starts with OP_SUPER and then +the class number that it inherits from (which must be an abstract class). +(Note this is the raw class number and is not the opcode number.) + + +=== Orders === + +The orders array is arranged as follows: + +* Index zero is not used. + +* After that, each entry, with the index being the order number, will be +the index within the orders array where the specification starts at. + +* Each specification simply consists of the opcode numbers and is +terminated by OP_RET. === Text encoding === The control codes for text formatting are: