Index: class.doc ================================================================== --- class.doc +++ class.doc @@ -1887,20 +1887,28 @@ Allows hitting to the right regardless of Shape, Volume, etc. In order to actually move when sliding to the right, both bit25 and bit27 must be set, and bit7 must be clear. bit28 * - Reserved for future. + This bit is set by the game engine if a warp has occurred. See the below + description of warping. You can also set this bit by yourself, and it + persists across restarts. If this bit is set, the moving object's + direction is updated after the movement if it is successful. bit29 * Reserved for future. bit30 Available for your own use. bit31 Available for your own use. + +The return value of HITBY can also be an object instead of a number. In +this case, a warp occurs. The movement is restarted, using the specified +object as the origin of the movement, and that object's direction as the +direction of movement. === Compatibility === Compatible objects have the following differences from the default: Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -784,25 +784,26 @@ static int move_dir(Uint32 from,Uint32 obj,Uint32 dir) { // This function is complicated, and there may be mistakes. Object*o; Object*oE; Object*oF; - Uint32 objE,objF,objLF,objRF; + Object*oW; + Uint32 objE,objF,objLF,objRF,objW; Uint32 hit=0; Uint32 vol; Value v; if(StackProtection()) Throw("Call stack overflow during movement"); if(obj==VOIDLINK) return 0; - o=objects[obj]; + oW=o=objects[objW=obj]; o->dir=dir=resolve_dir(obj,dir); if(o->weight>o->inertia) goto fail; o->inertia-=o->weight; restart: if(hit&0x100000) dir=o->dir; - objF=obj_dir(obj,dir); + objF=obj_dir(objW,dir); if(objF==VOIDLINK) goto fail; - if(hit) hit=0x800; + if(hit) hit=0x800|(hit&0x10000000); oF=objects[objF]; objLF=obj_dir(obj,(dir+1)&7); objRF=obj_dir(obj,(dir-1)&7); if(height_at(oF->x,oF->y)<=o->climb) hit|=0x200000; if(dir&1) { @@ -818,16 +819,17 @@ oE=objects[objE]; if(oE->height>0) { hit&=0xFC287000; v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(hit)); if(v.t) Throw("Type mismatch in HIT/HITBY"); - hit|=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1); + hit|=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1L); if(hit&8) goto fail; if(!(hit&0x11)) { - v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(hit)); + v=send_message(obj,objE,MSG_HITBY,NVALUE(oW->x),NVALUE(oW->y),NVALUE(hit)); + if(v.t>TY_MAXTYPE) goto warp; if(v.t) Throw("Type mismatch in HIT/HITBY"); - hit|=v.u&(classes[oE->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1); + hit|=v.u&(classes[oE->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1L); if(hit&8) goto fail; } } objE=obj_below(objE); } @@ -885,16 +887,23 @@ if(oE->height>0) { hit&=~7; // HIT/HITBY messages v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(hit)); if(v.t) Throw("Type mismatch in HIT/HITBY"); - hit|=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1); + hit|=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1L); if(hit&8) goto fail; if(!(hit&0x11)) { - v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(hit)); + v=send_message(obj,objE,MSG_HITBY,NVALUE(oW->x),NVALUE(oW->y),NVALUE(hit)); + if(v.t>TY_MAXTYPE) { + warp: + oW=objects[objW=v_object(v)]; + dir=oW->dir; + hit=0x10000000; + goto restart; + } if(v.t) Throw("Type mismatch in HIT/HITBY"); - hit|=v.u&(classes[oE->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1); + hit|=v.u&(classes[oE->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1L); } if(hit&0x108) goto fail; // Hardness/sharpness if(!(hit&0x22)) { if(o->sharp[dir>>1]>oE->hard[(dir^4)>>1] && !v_bool(destroy(obj,objE,2))) hit|=0x8004; @@ -932,16 +941,16 @@ if(oE->height>0) { hit&=~7; // HIT/HITBY messages v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(hit)); if(v.t) Throw("Type mismatch in HIT/HITBY"); - hit|=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1); + hit|=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1L); if(hit&8) goto otherside; if(!(hit&0x11)) { - v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(hit)); + v=send_message(obj,objE,MSG_HITBY,NVALUE(oW->x),NVALUE(oW->y),NVALUE(hit)); if(v.t) Throw("Type mismatch in HIT/HITBY"); - hit|=v.u&(classes[oE->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1); + hit|=v.u&(classes[oE->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1L); } if(hit&0x108) goto otherside; // Hardness/sharpness if(!(hit&0x22)) { if(o->sharp[dir>>1]>oE->hard[(dir^4)>>1] && !v_bool(destroy(obj,objE,2))) hit|=0x8004; @@ -970,11 +979,11 @@ v=send_message(objE,obj,MSG_HIT,NVALUE(oE->x),NVALUE(oE->y),NVALUE(hit)); if(v.t) Throw("Type mismatch in HIT/HITBY"); hit|=v.u&(classes[o->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1); if(hit&8) goto fail; if(!(hit&0x11)) { - v=send_message(obj,objE,MSG_HITBY,NVALUE(o->x),NVALUE(o->y),NVALUE(hit)); + v=send_message(obj,objE,MSG_HITBY,NVALUE(oW->x),NVALUE(oW->y),NVALUE(hit)); if(v.t) Throw("Type mismatch in HIT/HITBY"); hit|=v.u&(classes[oE->class]->cflags&CF_COMPATIBLE?0xC0098F7F:-1); } if(hit&0x108) goto fail; // Hardness/sharpness @@ -992,11 +1001,11 @@ if(move_to(from,obj,objects[objLF]->x,objects[objLF]->y)) goto success; } } } fail: if(hit&0x1000) goto success; o->inertia=0; return 0; - success: if(!(hit&0x4000)) o->oflags|=OF_MOVED; return 1; + success: if(!(hit&0x4000)) o->oflags|=OF_MOVED; if(hit&0x10000000) o->dir=dir; return 1; } static int jump_to(Uint32 from,Uint32 n,Uint32 x,Uint32 y) { int xx,yy; if(n==VOIDLINK) return 0;