Index: bindings.doc ================================================================== --- bindings.doc +++ bindings.doc @@ -102,10 +102,13 @@ Start or stop slow replay. Any move input also interrupts slow replay. '^s' Toggle solution replay. +'^x' + Cancel dead animation. + 'lo' Flash the specified location briefly. 'mi' Import a move list. The argument is a operating system command, that Index: class.doc ================================================================== --- class.doc +++ class.doc @@ -1136,18 +1136,32 @@ the message is sent even before the animation is actually visible), LOOP to play it in a loop, or OSCLOOP for an oscillating loop. The delay between frames is in centiseconds; the start and end are the image numbers in this class, and may be ascending or descending. +=Animate ( mode start end delay -- ) ** + Set animation for this object, in a similar but different way than + Animate does. There is no animation limit if this command is used, + and this does not set Image. The mode can be: 0=stop, 1=logical once, + 2=logical/visual once, 3=visual once, 4=visual looped, 5=visual looped + oscillating, 6=visual synchronized (the delay is now the slot number + instead), 7=logical once (also set Image). You can add 8 to set the + initial visible image to the Image variable instead of the start image, + and you can add 16 to start at half phase. + AnimateDead ( x y class start end delay -- ) Create a dead animation, at the specified coordinates. Give the class to use the pictures of, and the start and end image number, and the delay between frames in centiseconds. This will draw the animation on the screen without being associated with any object; this animation is purely visual and does not affect the game state. The animation will play once and then it will disappear. +=AnimateDead ( delay -- ) + Define the delay (in centiseconds) for the most recent dead animation. + If there isn't one, then this command does nothing. + Arg1 ( -- value ) The first message argument. =Arg1 ( value -- ) Allows setting the first message argument. This will last until the @@ -1484,10 +1498,13 @@ LocateMe ( -- ) Makes the current object especially visible. This is meant to help the player to notice where the "Hero" object is more easily, but you can use it to make other objects noticeable too if that is appropriate. +,LocateMe ( obj -- ) + Is like LocateMe but for a specified object instead of this one. + lor ( in1 in2 -- out ) Logical OR. LoseLevel ( -- ) Ends all execution and results in loss of game. @@ -1577,10 +1594,13 @@ MoveNumber ( -- number ) The current move number. This is initially zero, and is advanced after each input phase (before the beginning phase). +=MoveNumber ( number -- ) ** + Allows changing the MoveNumber value. + MoveTo ( x y -- bool ) ** Teleports this object to the specified coordinates; the MOVING message (and PLAYERMOVING if applicable) are sent to check if it is allowed. This also updates the Distance variable, and will deal with arrivals and departures, and send FLOATED and SUNK messages as appropriate. Index: default.heromeshrc ================================================================== --- default.heromeshrc +++ default.heromeshrc @@ -129,10 +129,11 @@ ?.gameKey.shift.f8: select 'ml',solution_move_list(1); ?.gameKey.f9: select 'lo',xy(o.x,o.y) from objects o,classes c on(o.class=c.id) where c.player; ?.gameKey.tab: ^I ?.gameKey.alt.G: ^g ?.gameKey.alt.P: ^p +?.gameKey.alt.X: ^x ?.gameKey.alt.leftbracket: select 'rs',-5; ?.gameKey.alt.rightbracket: select 'rs',+5; ?.gameKey.delete: ^- ?.gameKey.insert: ^+ Index: exec.c ================================================================== --- exec.c +++ exec.c @@ -179,10 +179,11 @@ d->x=o->x; d->y=o->y; d->s=o->anim->step[o->anim->vstep]; d->vtime=o->anim->vtime; d->vimage=o->anim->vimage; + d->delay=0; } static void v_animate_dead(Value x,Value y,Value c,Value s,Value e,Value z) { DeadAnimation*d; if(no_dead_anim || ndeadanim>=0x1000) return; @@ -199,10 +200,11 @@ d->s.start=s.u; d->s.end=e.u; d->s.speed=z.u; d->vtime=0; d->vimage=s.u; + d->delay=0; } void objtrash(Uint32 n) { Object*o=objects[n]; if(!o) return; @@ -326,10 +328,32 @@ } else if(an->status&ANISTAT_LOGICAL) { an->lstep=(an->lstep?:max_animation)-1; an->status&=~ANISTAT_LOGICAL; } } + +static void animate_ext(Uint32 n,Uint32 f,Uint32 a0,Uint32 a1,Uint32 t) { + Animation*an=objects[n]->anim; + objects[n]->image=a0; + if(!an) an=objects[n]->anim=animalloc(); + an->lstep=an->vstep=an->count=an->ltime=an->vtime=an->status=0; + an->step->start=a0; + an->step->end=a1; + an->step->speed=t; + an->vimage=(f&0x08?objects[n]->image:a0); + if(f&0x10) an->ltime=an->vtime=t/2; + switch(f&0x07) { + case 0: an->status=0; an->step->flag=0; break; + case 1: an->status=ANISTAT_LOGICAL; an->step->flag=ANI_ONCE; break; + case 2: an->status=ANISTAT_VISUAL|ANISTAT_LOGICAL; an->step->flag=ANI_ONCE; break; + case 3: an->status=ANISTAT_VISUAL; an->step->flag=ANI_ONCE; break; + case 4: an->status=ANISTAT_VISUAL; an->step->flag=ANI_LOOP; break; + case 5: an->status=ANISTAT_VISUAL; an->step->flag=ANI_LOOP|ANI_OSC; break; + case 6: an->status=ANISTAT_VISUAL|ANISTAT_SYNCHRONIZED; an->step->flag=ANI_LOOP|ANI_SYNC; an->step->slot=t&7; break; + case 7: an->status=ANISTAT_LOGICAL; an->step->flag=ANI_ONCE; objects[n]->image=a0; break; + } +} static void animate_sync(Uint32 n,Uint32 sl,Uint32 a0) { Animation*an=objects[n]->anim; objects[n]->image=a0; sl&=7; @@ -2378,12 +2402,14 @@ case 0x4000 ... 0x7FFF: StackReq(0,1); Push(CVALUE(code[ptr-1]-0x4000)); break; case 0x87E8 ... 0x87FF: StackReq(0,1); Push(NVALUE(1UL<<(code[ptr-1]&31))); break; case 0xC000 ... 0xFFFF: StackReq(0,1); Push(MVALUE((code[ptr-1]&0x3FFF)+256)); break; case OP_ADD: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t1.u+t2.u)); break; case OP_AND: StackReq(1,0); t1=Pop(); if(!v_bool(t1)) { Push(t1); ptr=code[ptr]; } else { ptr++; } break; - case OP_ANIMATE: StackReq(4,0); t4=Pop(); Numeric(t4); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); animate(obj,t1.u,t2.u,t3.u,t4.u); break; + case OP_ANIMATE: NoIgnore(); StackReq(4,0); t4=Pop(); Numeric(t4); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); animate(obj,t1.u,t2.u,t3.u,t4.u); break; + case OP_ANIMATE_E: NoIgnore(); StackReq(4,0); t4=Pop(); Numeric(t4); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); animate_ext(obj,t1.u,t2.u,t3.u,t4.u); break; case OP_ANIMATEDEAD: StackReq(6,0); t6=Pop(); t5=Pop(); t4=Pop(); t3=Pop(); t2=Pop(); t1=Pop(); v_animate_dead(t1,t2,t3,t4,t5,t6); break; + case OP_ANIMATEDEAD_E: StackReq(1,0); t1=Pop(); if(ndeadanim && !t1.t) deadanim[ndeadanim-1].delay=t1.u; break; case OP_ARG1: StackReq(0,1); Push(msgvars.arg1); break; case OP_ARG1_E: StackReq(1,0); msgvars.arg1=Pop(); break; case OP_ARG2: StackReq(0,1); Push(msgvars.arg2); break; case OP_ARG2_E: StackReq(1,0); msgvars.arg2=Pop(); break; case OP_ARG3: StackReq(0,1); Push(msgvars.arg3); break; @@ -2561,10 +2587,11 @@ case OP_LEVEL: StackReq(0,1); Push(NVALUE(level_code)); break; case OP_LNOT: StackReq(1,1); if(v_bool(Pop())) Push(NVALUE(0)); else Push(NVALUE(1)); break; case OP_LOC: StackReq(0,2); Push(NVALUE(o->x)); Push(NVALUE(o->y)); break; case OP_LOC_C: StackReq(1,2); i=v_object(Pop()); Push(NVALUE(i==VOIDLINK?0:objects[i]->x)); Push(NVALUE(i==VOIDLINK?0:objects[i]->y)); break; case OP_LOCATEME: locate_me(o->x,o->y); break; + case OP_LOCATEME_C: StackReq(1,0); i=v_object(Pop()); if(i!=VOIDLINK) locate_me(objects[i]->x,objects[i]->y); break; case OP_LOR: StackReq(2,1); t1=Pop(); t2=Pop(); if(v_bool(t1) || v_bool(t2)) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_LOSELEVEL: gameover=-1; Throw(0); break; case OP_LSH: StackReq(2,1); t2=Pop(); Numeric(t2); t1=Pop(); Numeric(t1); Push(NVALUE(t2.u&~31?0:t1.u<oflags&OF_MOVED) Push(NVALUE(1)); else Push(NVALUE(0)); break; case OP_MOVED_C: StackReq(1,1); GetFlagOf(OF_MOVED); break; case OP_MOVED_E: NoIgnore(); StackReq(1,0); if(v_bool(Pop())) o->oflags|=OF_MOVED; else o->oflags&=~OF_MOVED; break; case OP_MOVED_EC: NoIgnore(); StackReq(2,0); SetFlagOf(OF_MOVED); break; case OP_MOVENUMBER: StackReq(0,1); Push(NVALUE(move_number)); break; + case OP_MOVENUMBER_E: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); move_number=t1.u; break; case OP_MOVEPLUS: NoIgnore(); StackReq(1,1); t1=Pop(); Numeric(t1); o->inertia+=o->strength; Push(NVALUE(move_dir(obj,obj,t1.u))); break; case OP_MOVEPLUS_C: NoIgnore(); StackReq(2,1); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i==VOIDLINK) Push(NVALUE(0)); else {objects[i]->inertia+=o->strength;Push(NVALUE(move_dir(obj,i,t1.u)));} break; case OP_MOVEPLUS_D: NoIgnore(); StackReq(1,0); t1=Pop(); Numeric(t1); o->inertia+=o->strength; move_dir(obj,obj,t1.u); break; case OP_MOVEPLUS_CD: NoIgnore(); StackReq(2,0); t1=Pop(); Numeric(t1); i=v_object(Pop()); if(i!=VOIDLINK) { objects[i]->inertia+=o->strength; move_dir(obj,i,t1.u); } break; case OP_MOVETO: NoIgnore(); StackReq(2,1); t3=Pop(); Numeric(t3); t2=Pop(); Numeric(t2); Push(NVALUE(move_to(obj,obj,t2.u,t3.u))); break; Index: game.c ================================================================== --- game.c +++ game.c @@ -196,10 +196,14 @@ if(ndeadanim) { for(i=0;ix,d->y); if(!d->s.flag) continue; + if(d->delay) { + --d->delay; + continue; + } if(d->vimageclass]->nimages) draw_picture((d->x-1)*picture_size+left_margin,(d->y-1)*picture_size,classes[d->class]->images[d->vimage]&0x7FFF); if(++d->vtime>=d->s.speed) { if(d->vimage==d->s.end) d->s.flag=0; if(d->s.end>=d->s.start) ++d->vimage; else --d->vimage; @@ -784,10 +788,13 @@ inserting=0; if(replay_count) save_replay(); solution_replay^=1; if(replay_count) replay_count=0,begin_level(level_id); else load_replay(); return 1; + case '^x': // Cancel dead animation + ndeadanim=0; + return prev; case 'go': // Select level begin_level(number); return 1; case 'lo': // Locate me locate_me(number&63?:64,number/64?:64); Index: heromesh.h ================================================================== --- heromesh.h +++ heromesh.h @@ -219,11 +219,11 @@ }; } AnimationStep; typedef struct { Uint8 x,y,vtime,vimage; - Uint16 class; + Uint16 class,delay; AnimationStep s; } DeadAnimation; #define ANISTAT_LOGICAL 0x01 #define ANISTAT_VISUAL 0x02 Index: instruc ================================================================== --- instruc +++ instruc @@ -189,11 +189,11 @@ Msg From =Arg1 =Arg2 =Arg3 -MoveNumber +=MoveNumber Level Key =Finished ; Class definitions @@ -208,12 +208,12 @@ -EditorHelp -Others -SUBS ; Main operations / miscellaneous -Animate -AnimateDead +=Animate +=AnimateDead ,Assassinate ; destroy without sending any messages .Broadcast BroadcastAnd ; Broadcast, but result is AND of return values BroadcastAndEx *BroadcastClass ; for (Broadcast [class]) @@ -237,11 +237,11 @@ HitMe IgnoreKey .,IntMove ; move without initializing Inertia .,JumpTo ,Loc ; same as: Xloc Yloc -LocateMe +,LocateMe LoseLevel ,Manhattan MaxInventory ; error if more than that many slots in inventory .,Move .,MovePlus "Move+" ; obj.Inertia+=Strength instead of obj.Inertia=Strength Index: instruc.h ================================================================== --- instruc.h +++ instruc.h @@ -278,10 +278,11 @@ #define OP_ARG2 32892 #define OP_ARG2_E 36988 #define OP_ARG3 32893 #define OP_ARG3_E 36989 #define OP_MOVENUMBER 32894 +#define OP_MOVENUMBER_E 36990 #define OP_LEVEL 32895 #define OP_KEY 32896 #define OP_FINISHED 32897 #define OP_FINISHED_E 36993 #define OP_BACKGROUND 32898 @@ -294,11 +295,13 @@ #define OP_HELP 32905 #define OP_EDITORHELP 32906 #define OP_OTHERS 32907 #define OP_SUBS 32908 #define OP_ANIMATE 32909 +#define OP_ANIMATE_E 37005 #define OP_ANIMATEDEAD 32910 +#define OP_ANIMATEDEAD_E 37006 #define OP_ASSASSINATE 32911 #define OP_ASSASSINATE_C 34959 #define OP_BROADCAST 32912 #define OP_BROADCAST_D 41104 #define OP_BROADCASTAND 32913 @@ -340,10 +343,11 @@ #define OP_JUMPTO_D 41128 #define OP_JUMPTO_CD 43176 #define OP_LOC 32937 #define OP_LOC_C 34985 #define OP_LOCATEME 32938 +#define OP_LOCATEME_C 34986 #define OP_LOSELEVEL 32939 #define OP_MANHATTAN 32940 #define OP_MANHATTAN_C 34988 #define OP_MAXINVENTORY 32941 #define OP_MOVE 32942 @@ -469,12 +473,12 @@ {".",10518528}, {"/",8486940}, {"ANHH",8389394}, {"ARRIVED",8389124}, {"Abstract",8683756}, -{"Animate",8421517}, -{"AnimateDead",8421518}, +{"Animate",8552589}, +{"AnimateDead",8552590}, {"Arg1",8552571}, {"Arg2",8552572}, {"Arg3",8552573}, {"Array",8683739}, {"ArrayCell",8421599}, @@ -595,11 +599,11 @@ {"LF",9437193}, {"LOCK",8389408}, {"LOOP",8388610}, {"Level",8421503}, {"Loc",8487081}, -{"LocateMe",8421546}, +{"LocateMe",8487082}, {"LoseLevel",8421547}, {"MOVED",8389127}, {"MOVING",8389130}, {"Manhattan",8487084}, {"MaxInventory",8421549}, @@ -610,11 +614,11 @@ {"Misc5",9142368}, {"Misc6",9142370}, {"Misc7",9142372}, {"Move",10584238}, {"Move+",10584239}, -{"MoveNumber",8421502}, +{"MoveNumber",8552574}, {"MoveTo",10584240}, {"Moved",8618097}, {"Moving",8618098}, {"Msg",8421497}, {"N",9437186},