/[enigma]/enigma/src/objects.cc
ViewVC logotype

Diff of /enigma/src/objects.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.61 by dheck, Wed May 7 20:40:12 2003 UTC revision 1.62 by reallysoft, Thu May 8 00:03:59 2003 UTC
# Line 182  GridObject::play_sound(const char *name) Line 182  GridObject::play_sound(const char *name)
182  //======================================================================  //======================================================================
183    
184  Floor::Floor(const char *kind, double friction, double mfactor)  Floor::Floor(const char *kind, double friction, double mfactor)
185  : TGridObject<GRID_FLOOR>(kind),  : TGridObject<GRID_FLOOR>(kind),
186    traits (kind, friction, mfactor, FLOOR_Normal)    traits (kind, friction, mfactor, FLOOR_Normal)
187  {  {
188  }  }
# Line 1575  namespace Line 1575  namespace
1575          void alarm() {          void alarm() {
1576              state = MOVING;              state = MOVING;
1577              GridPos p = get_pos();              GridPos p = get_pos();
 #if defined(USE_IMPULSES)  
1578              if (move_stone(get_dir())) {              if (move_stone(get_dir())) {
 #else  
             if (world::MaybeMoveStone(p, get_dir())) {  
 #endif // USE_IMPULSES  
1579                  // send a message to the stone that's blocking our way                  // send a message to the stone that's blocking our way
1580                  Stone *st = GetStone(move(move(p,get_dir()),get_dir()));                  Stone *st = GetStone(move(move(p,get_dir()),get_dir()));
1581                  if( st) SendMessage(st, "trigger", Value(get_dir()));                  if( st) SendMessage(st, "trigger", Value(get_dir()));
# Line 1702  namespace Line 1698  namespace
1698          bool on_laserhit(Direction dir) {          bool on_laserhit(Direction dir) {
1699              return get_connections() == 0;              return get_connections() == 0;
1700          }          }
1701  #if defined(USE_IMPULSES)  
1702          virtual void on_impulse(Direction dir);          virtual void on_impulse(Direction dir);
 #endif // USE_IMPULSES  
1703    
1704          void init_model();          void init_model();
1705          StoneResponse collision_response(const StoneContact &sc);          StoneResponse collision_response(const StoneContact &sc);
# Line 1906  PuzzleStone::collision_response(const St Line 1901  PuzzleStone::collision_response(const St
1901      return STONE_REBOUND;      return STONE_REBOUND;
1902  }  }
1903    
 #if defined(USE_IMPULSES)  
1904  void  void
1905  PuzzleStone::on_impulse(Direction dir) {  PuzzleStone::on_impulse(Direction dir) {
 //     fprintf(stderr, "PuzzleStone::on_impulse(%s)\n", to_suffix(dir).c_str());  
1906      Cluster c;      Cluster c;
1907      bool    is_complete = find_cluster(c);      bool    is_complete = find_cluster(c);
1908      maybe_move_cluster(c, is_complete, dir);      maybe_move_cluster(c, is_complete, dir);
# Line 1944  PuzzleStone::actor_hit(const StoneContac Line 1937  PuzzleStone::actor_hit(const StoneContac
1937          }          }
1938      }      }
1939      else if (move_impulse && hit_dir != NODIR) {      else if (move_impulse && hit_dir != NODIR) {
1940          SendImpulse(get_pos(), hit_dir);          SendImpulse(get_pos(), hit_dir, a);
1941      }      }
1942  }  }
 #else  
 void  
 PuzzleStone::actor_hit(const StoneContact &sc)  
 {  
     if (get_connections() == NODIRBIT)  
         return;  
   
     Actor *a = sc.actor;  
   
     bool move_impulse= (a->get_vel()*sc.normal < -4);  
     Direction hit_dir=reverse(contact_face(sc));  
   
     if (wielded_item_is(a, "it-magicwand")) {  
         if (cluster_complete()) {  
             // make all cluster stones explode  
             return;  
         }  
         else if (hit_dir != NODIR) {  
             Cluster c;  
             find_row_or_column_cluster(c, get_pos(), hit_dir);  
   
             bool is_complete = false;  
   
             if (move_impulse)  
                 maybe_move_cluster(c, is_complete, hit_dir);  
             else  
                 rotate_cluster(c);  
         }  
     }  
     else if (move_impulse && hit_dir != NODIR) {  
         Cluster c;  
         bool is_complete = find_cluster(c);  
         maybe_move_cluster(c, is_complete, hit_dir);  
     }  
 }  
 #endif // USE_IMPULSES  
   
1943    
1944  //----------------------------------------  //----------------------------------------
1945  // DoorBase  // DoorBase
# Line 2582  namespace Line 2538  namespace
2538              notify_item(false);              notify_item(false);
2539          }          }
2540    
 #if defined(USE_IMPULSES)  
2541          void on_impulse(Direction dir);          void on_impulse(Direction dir);
 #endif // USE_IMPULSES  
2542    
2543          void init_model() {          void init_model() {
2544              char x[20];              char x[20];
# Line 2708  ShogunStone::transfer_smallest_hole(Grid Line 2662  ShogunStone::transfer_smallest_hole(Grid
2662      return nh;      return nh;
2663  }  }
2664    
 #if defined(USE_IMPULSES)  
2665  void  void
2666  ShogunStone::actor_hit(const StoneContact &sc)  ShogunStone::actor_hit(const StoneContact &sc)
2667  {  {
# Line 2719  ShogunStone::actor_hit(const StoneContac Line 2672  ShogunStone::actor_hit(const StoneContac
2672      if (hit_dir == NODIR || !move_impulse)      if (hit_dir == NODIR || !move_impulse)
2673          return;          return;
2674    
2675      SendImpulse(get_pos(), hit_dir);      SendImpulse(get_pos(), hit_dir, a);
2676  }  }
2677    
2678  void  void
# Line 2733  ShogunStone::on_impulse(Direction dir) { Line 2686  ShogunStone::on_impulse(Direction dir) {
2686      }      }
2687  }  }
2688    
 #else  
 void  
 ShogunStone::actor_hit(const StoneContact &sc)  
 {  
     Actor     *a            = sc.actor;  
     bool       move_impulse = (a->get_vel()*sc.normal < -4);  
     Direction  hit_dir      = reverse(contact_face(sc));  
   
     if (hit_dir == NODIR || !move_impulse)  
         return;  
   
     Holes holes    = get_holes();  
     Holes newholes = transfer_smallest_hole(move(get_pos(), hit_dir));  
   
     if (newholes != holes) {  
         play_sound("st-move");  
     }  
 }  
 #endif // USE_IMPULSES  
   
   
2689  //----------------------------------------  //----------------------------------------
2690  // FartStone  // FartStone
2691  //----------------------------------------  //----------------------------------------
# Line 2944  namespace Line 2876  namespace
2876    
2877          void change_state(State st);          void change_state(State st);
2878    
 #if defined(USE_IMPULSES)  
2879          virtual void on_impulse(Direction dir) {          virtual void on_impulse(Direction dir) {
 //             fprintf(stderr, "StoneImpulse_Base::on_impulse(%s)\n", to_suffix(dir).c_str());  
2880              incoming = dir;              incoming = dir;
2881              change_state(PULSING);              change_state(PULSING);
2882          }          }
 #endif // USE_IMPULSES  
2883    
2884      private:      private:
2885    
2886          virtual void notify_state(State st) = 0;          virtual void notify_state(State st) = 0;
2887    
2888          void message(const string &m, const Value &value) {          void message(const string &m, const Value &value) {
 #if defined(USE_IMPULSES)  
2889              if (m=="trigger") {              if (m=="trigger") {
2890                  incoming = (value.get_type() == Value::DOUBLE)                  incoming = (value.get_type() == Value::DOUBLE)
2891                      ? Direction(value.get_double()+0.1)                      ? Direction(value.get_double()+0.1)
# Line 2965  namespace Line 2893  namespace
2893    
2894                  change_state(PULSING);                  change_state(PULSING);
2895              }              }
 #else  
             if (m=="trigger" || m=="stoneimpulse")  
                 change_state(PULSING);  
 #endif // USE_IMPULSES  
2896          }          }
2897    
2898          void animcb() {          void animcb() {
# Line 3001  StoneImpulse_Base::change_state(State st Line 2925  StoneImpulse_Base::change_state(State st
2925          break;          break;
2926      case CLOSING:      case CLOSING:
2927          {          {
 #if defined(USE_IMPULSES)  
   
 //             fprintf(stderr, "Sending impulses (incoming = %s)\n", to_suffix(incoming).c_str());  
   
2928              GridPos targetpos[4];              GridPos targetpos[4];
2929              bool    haveStone[4];              bool    haveStone[4];
2930    
# Line 3016  StoneImpulse_Base::change_state(State st Line 2936  StoneImpulse_Base::change_state(State st
2936              for (int d = int(incoming)+1; d <= int(incoming)+4; ++d) {              for (int d = int(incoming)+1; d <= int(incoming)+4; ++d) {
2937                  int D = d%4;                  int D = d%4;
2938                  if (haveStone[D]) {                  if (haveStone[D]) {
2939                      SendImpulse(targetpos[D], Direction(D));                      SendImpulse(targetpos[D], Direction(D), this);
2940                  }                  }
2941              }              }
2942    
2943              incoming = NODIR;   // forget impulse direction              incoming = NODIR;   // forget impulse direction
 #else  
             MaybeMoveStone( move( p, NORTH), NORTH);  
             MaybeMoveStone( move( p, EAST), EAST);  
             MaybeMoveStone( move( p, SOUTH), SOUTH);  
             MaybeMoveStone( move( p, WEST), WEST);  
             SendMessage (GetStone(move(p, NORTH)), "stoneimpulse");  
             SendMessage (GetStone(move(p, EAST)), "stoneimpulse");  
             SendMessage (GetStone(move(p, SOUTH)), "stoneimpulse");  
             SendMessage (GetStone(move(p, WEST)), "stoneimpulse");  
 #endif // USE_IMPULSES  
2944              break;              break;
2945          }          }
2946      case IDLE:      case IDLE:
# Line 3124  namespace Line 3034  namespace
3034    
3035          // Stone interface:          // Stone interface:
3036    
 #if defined(USE_IMPULSES)  
3037          void on_impulse(Direction dir) {          void on_impulse(Direction dir) {
 //             fprintf(stderr, "MovableImpulseStone::on_impulse(%s)\n", to_suffix(dir).c_str());  
3038              if (move_stone(dir)) {              if (move_stone(dir)) {
3039                  // on_move changes state to PULSING                  // on_move changes state to PULSING
3040                  incoming = dir;                  incoming = dir;
# Line 3135  namespace Line 3043  namespace
3043                  StoneImpulse_Base::on_impulse(dir);                  StoneImpulse_Base::on_impulse(dir);
3044              }              }
3045          }          }
3046    
3047          void actor_hit(const StoneContact &sc) {          void actor_hit(const StoneContact &sc) {
3048              ActorInfo *ai  = sc.actor->get_actorinfo();              ActorInfo *ai  = sc.actor->get_actorinfo();
3049              Direction  dir = contact_face(sc);              Direction  dir = contact_face(sc);
3050    
3051                // If the speed component towards the face of the stone is large
3052                // enough (and actually pointing towards the stone), consider
3053                // moving the stone.
3054              if (dir!=enigma::NODIR && ai->vel * sc.normal < -4) {              if (dir!=enigma::NODIR && ai->vel * sc.normal < -4) {
3055                  SendImpulse(get_pos(), reverse(dir));                  SendImpulse(get_pos(), reverse(dir), sc.actor);
3056              }              }
3057              else {              else {
3058                  incoming = NODIR; // @@@ problem!                  incoming = NODIR; // @@@ problem!
# Line 3148  namespace Line 3060  namespace
3060              }              }
3061          }          }
3062    
 #else  
         void actor_hit(const StoneContact &sc)  
         {  
             ActorInfo *ai = sc.actor->get_actorinfo();  
   
             // If the speed component towards the face of the stone is large  
             // enough (and actually pointing towards the stone), consider  
             // moving the stone.  
   
             Direction dir   = contact_face(sc);  
             bool      moved = false;  
   
             if (dir!=enigma::NODIR && ai->vel * sc.normal < -4) {  
                 moved = MaybeMoveStone(get_pos(), reverse(dir));  
             }  
   
             // if the stone moves the state is changed to PULSING by on_move(),  
             // otherwise do it here  
             if (!moved) change_state(PULSING);  
         }  
   
 #endif // USE_IMPULSES  
   
3063          void on_move() {          void on_move() {
3064              if (state != IDLE) change_state(IDLE);              if (state != IDLE) change_state(IDLE);
3065              if (state == IDLE) change_state(PULSING);              if (state == IDLE) change_state(PULSING);
# Line 3934  namespace Line 3823  namespace
3823      /*      /*
3824      ** The stone at the center of a turnstile      ** The stone at the center of a turnstile
3825      */      */
3826      class Turnstile_Pivot : public Stone {      class Turnstile_Pivot_Base : public Stone {
         CLONEOBJ(Turnstile_Pivot);  
   
         DirectionBits arms_present();  
         bool no_stone (int xoff, int yoff);  
         void remove_arms (DirectionBits arms);  
         void set_arm (Direction dir);  
3827      public:      public:
3828          Turnstile_Pivot() : Stone ("st-turnstile") {}          Turnstile_Pivot_Base(const char *kind) : Stone (kind) {}
3829    
3830          bool rotate_right();          bool rotate_right();
3831          bool rotate_left();          bool rotate_left();
3832    
3833      private:      private:
3834          void can_rotate() {          DirectionBits arms_present();
3835              set_anim("st-turnstile-anim");          bool          no_stone (int xoff, int yoff);
         }  
         void animcb() {  
             set_model("st-turnstile");  
         }  
3836    
3837            void set_arm (Direction dir);
3838            void set_arms (DirectionBits arms);
3839            void remove_arms (DirectionBits arms);
3840    
3841            void animcb() { set_model(model()); }
3842          void warpActorsInRange(bool clockwise);          void warpActorsInRange(bool clockwise);
3843    
3844            virtual const char *model() const    = 0;
3845            virtual const char *anim() const     = 0;
3846            virtual bool oxyd_compatible() const = 0;
3847        };
3848    
3849        class Turnstile_Pivot : public Turnstile_Pivot_Base {
3850            CLONEOBJ(Turnstile_Pivot);
3851        public:
3852            Turnstile_Pivot() : Turnstile_Pivot_Base(model()) {}
3853    
3854            const char *model() const { return "st-turnstile"; }
3855            const char *anim() const  { return "st-turnstile-anim"; }
3856            bool oxyd_compatible() const { return true; }
3857        };
3858    
3859        class Turnstile_Pivot_Green : public Turnstile_Pivot_Base {
3860            CLONEOBJ(Turnstile_Pivot_Green);
3861        public:
3862            Turnstile_Pivot_Green() : Turnstile_Pivot_Base(model()) {}
3863    
3864            const char *model() const { return "st-turnstile-green"; }
3865            const char *anim() const  { return "st-turnstile-green-anim"; }
3866            bool oxyd_compatible() const { return false; }
3867      };      };
3868    
3869      /*      /*
# Line 3963  namespace Line 3873  namespace
3873          virtual Direction get_dir() const = 0;          virtual Direction get_dir() const = 0;
3874    
3875          void actor_hit(const StoneContact &sc);          void actor_hit(const StoneContact &sc);
 #if defined(USE_IMPULSES  )  
3876          void on_impulse(Direction dir);          void on_impulse(Direction dir);
 #endif // USE_IMPULSES  
3877    
3878          Turnstile_Pivot *get_pivot()          Turnstile_Pivot_Base *get_pivot() {
         {  
3879              Stone *st = GetStone (move (get_pos(), reverse(get_dir())));              Stone *st = GetStone (move (get_pos(), reverse(get_dir())));
3880              return dynamic_cast<Turnstile_Pivot*>(st);              return dynamic_cast<Turnstile_Pivot_Base*>(st);
3881          }          }
3882      protected:      protected:
3883          Turnstile_Arm (const char *kind) : Stone(kind)          Turnstile_Arm (const char *kind) : Stone(kind)
# Line 4023  namespace Line 3930  namespace
3930      };      };
3931  }  }
3932    
 #if defined(USE_IMPULSES)  
   
3933  void  void
3934  Turnstile_Pivot::warpActorsInRange(bool clockwise) {  Turnstile_Pivot_Base::warpActorsInRange(bool clockwise) {
3935      // the turnstile itself already has been rotated      // the turnstile itself already has been rotated
3936      // now handle all actors in Range      // now handle all actors in Range
3937    
3938      GridPos        pv_pos = get_pos();      GridPos pv_pos = get_pos();
3939      V2             pv_center(pv_pos.x+.5, pv_pos.y+.5);      V2      pv_center(pv_pos.x+.5, pv_pos.y+.5);
3940    
3941        const int to_index[3][3] = {
3942            { 0, 7, 6 }, // x == 0
3943            { 1,-1, 5 }, // x == 1
3944            { 2, 3, 4 }  // x == 2
3945        };
3946    
3947        // for each field calculate whether an arm has passed by:
3948        bool arm_seen[8];
3949        {
3950            const DirectionBits neededArm[2][8] = {
3951                // anticlockwise :
3952                { WESTBIT, NORTHBIT, NORTHBIT, EASTBIT, EASTBIT, SOUTHBIT, SOUTHBIT, WESTBIT },
3953                // clockwise :
3954                { NORTHBIT, NORTHBIT, EASTBIT, EASTBIT, SOUTHBIT, SOUTHBIT, WESTBIT, WESTBIT }
3955            };
3956            DirectionBits arms = arms_present(); // already the rotated state
3957            assert(arms); // pivots w/o arms should not rotate
3958    
3959            for (int i = 0; i<8; ++i) {
3960                arm_seen[i] = arms & neededArm[clockwise][i];
3961            }
3962        }
3963    
3964      vector<Actor*> actorsInRange;      vector<Actor*> actorsInRange;
3965    
3966      // tested range is sqrt(sqr(1.5)+sqr(0.5)) ( = radius hit by turnstile) + 19/64 ( = max. actor radius)      // tested range is sqrt(sqr(1.5)+sqr(0.5)) ( = radius hit by turnstile) + 19/64 ( = max. actor radius)
# Line 4046  Turnstile_Pivot::warpActorsInRange(bool Line 3975  Turnstile_Pivot::warpActorsInRange(bool
3975                  // @@@ FIXME: test if actor was hit by turnstile -> set actor speed                  // @@@ FIXME: test if actor was hit by turnstile -> set actor speed
3976              }              }
3977              else {              // actor is inside the turnstile              else {              // actor is inside the turnstile
                 const int to_index[3][3] = {  
                     { 0, 7, 6 }, // x == 0  
                     { 1,-1, 5 }, // x == 1  
                     { 2, 3, 4 }  // x == 2  
                 };  
3978                  const int to_x[8] = { -1, 0, 1, 1, 1, 0, -1, -1 };                  const int to_x[8] = { -1, 0, 1, 1, 1, 0, -1, -1 };
3979                  const int to_y[8] = { -1, -1, -1, 0, 1, 1, 1, 0 };                  const int to_y[8] = { -1, -1, -1, 0, 1, 1, 1, 0 };
3980    
3981                  int idx_source = to_index[dx+1][dy+1];                  int idx_source = to_index[dx+1][dy+1];
3982                  if (idx_source == -1) continue;                  assert(idx_source != -1); // actor inside pivot -- impossible
3983    
3984  #define OXYD_COMPATIBLE                  const int rot_index[4][8] = {
3985  #ifdef OXYD_COMPATIBLE                      { 6,  0, 0,  2, 2,  4, 4,  6 }, // anticlockwise
3986                  const int rot_index[2][8] = {                      { 2,  2, 4,  4, 6,  6, 0,  0 }, // clockwise
3987                      { 6, -1, 0, -1, 2, -1, 4, -1 }, // anticlockwise                      { 6, -1, 0, -1, 2, -1, 4, -1 }, // anticlockwise (oxyd-compatible)
3988                      { 2, -1, 4, -1, 6, -1, 0, -1 }  // clockwise                      { 2, -1, 4, -1, 6, -1, 0, -1 }, // clockwise (oxyd-compatible)
3989                  };                  };
3990    
3991                  int idx_target = rot_index[clockwise][idx_source];                  bool compatible = oxyd_compatible();
3992                  assert(idx_target >= -1 && idx_target < 8 && (idx_target%2) == 0);                  int  idx_target = rot_index[clockwise+2*compatible][idx_source]; // destination index
3993    
3994                  GridPos ac_target_pos(pv_pos.x+to_x[idx_target], pv_pos.y+to_y[idx_target]);                  enum { STAY, WARP, SHATTER } action = STAY;
                 world::WarpActor(*ac, ac_target_pos.x+.5, ac_target_pos.y+.5);  
3995    
3996  #else                  if (compatible) {
3997                  const int rot_index[2][8] = {                      bool is_impulse_sender = (*ac == dynamic_cast<Actor*>(ImpulseSender()));
                     { 6, 0, 0, 2, 2, 4, 4, 6 }, // anticlockwise  
                     { 2, 2, 4, 4, 6, 6, 0, 0 }  // clockwise  
                 };  
   
                 const DirectionBits neededArm[2][8] = {  
                     // anticlockwise  
                     { WESTBIT, NORTHBIT, NORTHBIT, EASTBIT, EASTBIT, SOUTHBIT, SOUTHBIT, WESTBIT },  
                     // clockwise  
                     { NORTHBIT, NORTHBIT, EASTBIT, EASTBIT, SOUTHBIT, SOUTHBIT, WESTBIT, WESTBIT }  
                 };  
3998    
3999                  DirectionBits arms = arms_present(); // already the rotated state                      if (is_impulse_sender) {
4000                            action = WARP;
4001                        }
4002                        else { // other actors
4003                            if (arm_seen[idx_source]) { // this actor has been hit by an arm
4004                                action = SHATTER;
4005                            }
4006                        }
4007                    }
4008                    else {          // not oxyd-compatible
4009                        if (arm_seen[idx_source]) {
4010                            action = WARP;
4011                        }
4012                        // @@@ FIXME: shattered actors are warped
4013                    }
4014    
4015                  if (arms & neededArm[clockwise][idx_source]) { // does an arm exist, which might move the actor?                  switch (action) {
4016                      int idx_target = rot_index[clockwise][idx_source];                      case WARP:  {
4017                      assert(idx_target >= 0 && idx_target < 8);                          GridPos ac_target_pos(pv_pos.x+to_x[idx_target], pv_pos.y+to_y[idx_target]);
4018                            world::WarpActor(*ac, ac_target_pos.x+.5, ac_target_pos.y+.5);
4019    
4020                      GridPos ac_target_pos(pv_pos.x+to_x[idx_target], pv_pos.y+to_y[idx_target]);                          Stone *st = GetStone(ac_target_pos);
4021                      world::WarpActor(*ac, ac_target_pos.x+.5, ac_target_pos.y+.5);                          if (!st) break;
4022    
4023                      if (Stone *st = GetStone(ac_target_pos)) { // destination is blocked                          // destination is blocked
                         Turnstile_Arm *arm     = dynamic_cast<Turnstile_Arm*>(st);  
                         bool           shatter = true;  
4024    
4025                          if (arm) { // if stone is turnstile arm -> hit it!                          Turnstile_Arm *arm = dynamic_cast<Turnstile_Arm*>(st);
4026                            if (arm && !compatible) { // if blocking stone is turnstile arm -> hit it!
4027                              const int impulse_dir[2][8] = {                              const int impulse_dir[2][8] = {
4028                                  // anticlockwise                                  // anticlockwise
4029                                  { SOUTHBIT|WESTBIT, WESTBIT, NORTHBIT|WESTBIT, NORTHBIT,                                  { SOUTHBIT|WESTBIT, WESTBIT, NORTHBIT|WESTBIT, NORTHBIT,
# Line 4106  Turnstile_Pivot::warpActorsInRange(bool Line 4033  Turnstile_Pivot::warpActorsInRange(bool
4033                                    SOUTHBIT|WESTBIT, WESTBIT, NORTHBIT|WESTBIT, NORTHBIT }                                    SOUTHBIT|WESTBIT, WESTBIT, NORTHBIT|WESTBIT, NORTHBIT }
4034                              };                              };
4035    
4036                              DirectionBits possible_impulses =                              DirectionBits possible_impulses =
4037                                  static_cast<DirectionBits>(impulse_dir[clockwise][idx_target]);                                  static_cast<DirectionBits>(impulse_dir[clockwise][idx_target]);
4038    
4039                              for (int d = 0; d<4; ++d) {                              for (int d = 0; d<4; ++d) {
4040                                  if (has_dir(possible_impulses, Direction(d))) {                                  if (has_dir(possible_impulses, Direction(d))) {
4041                                      SendImpulse(ac_target_pos, Direction(d));                                      SendImpulse(ac_target_pos, Direction(d), *ac);
4042                                  }                                  }
4043                              }                              }
4044    
4045                              if (GetStone(ac_target_pos) == 0) {                              if (GetStone(ac_target_pos) == 0) { // arm disappeared
4046                                  shatter = false;                                  break;
4047                              }                              }
4048                          }                          }
4049                            // fall-through (if arm didn't rotate or other stone was blocking)
4050                          if (shatter) SendMessage(*ac, "shatter");                      }
4051                        case SHATTER: {
4052                            SendMessage(*ac, "shatter");
4053                            break;
4054                      }                      }
4055                  }                  }
4056    
4057                  // @@@ FIXME: it's possible that two actors are moved to the same destination field.                  // @@@ FIXME: it's possible that two actors are moved to the same destination field.
4058                  // In that case the second actor is put on top of the first actor                  // In that case the second actor is put on top of the first actor
4059                  // (happens only with three balls or pullers/impulsestones)                  // (happens only in non-oxyd-compat-mode with three balls or pullers/impulsestones)
4060                  //                  //
4061                  // Note: With black and whiteball it's normally no problem,                  // Note: With black and whiteball it's normally no problem,
4062                  // because when one of the actors was moving, it's looking natural.                  // because when one of the actors was moving, it's looking natural.
4063                  // Problems occur when small balls come into play.                  // Problems occur when small balls come into play.
 #endif  
   
                 // @@@ FIXME: shattered actors are warped  
4064              }              }
4065          }          }
4066      }      }
4067    
4068      // @@@ FIXME: should some items warp ?      // @@@ FIXME: handle items in range (using on_stonehit())
4069  }  }
4070    
4071  void  void
# Line 4151  Turnstile_Arm::on_impulse(Direction dir) Line 4078  Turnstile_Arm::on_impulse(Direction dir)
4078          { ROTL, stay, ROTR, stay } // north arm          { ROTL, stay, ROTR, stay } // north arm
4079      };      };
4080    
4081      Turnstile_Pivot *pivot = get_pivot();      Turnstile_Pivot_Base *pivot = get_pivot();
4082    
4083      if (pivot) {      if (pivot) {
4084          Action a = actions[get_dir()][dir];          Action a = actions[get_dir()][dir];
# Line 4172  Turnstile_Arm::actor_hit(const StoneCont Line 4099  Turnstile_Arm::actor_hit(const StoneCont
4099      Direction dir = reverse(contact_face(sc));      Direction dir = reverse(contact_face(sc));
4100      if (dir!=enigma::NODIR && ai->vel * sc.normal < -4)      if (dir!=enigma::NODIR && ai->vel * sc.normal < -4)
4101      {      {
4102          SendImpulse(get_pos(), dir);          SendImpulse(get_pos(), dir, sc.actor);
4103      }      }
4104  }  }
4105    
4106  #else  #if 0 //  old code :
4107    
4108  void  void
4109  Turnstile_Arm::actor_hit(const StoneContact &sc)  Turnstile_Arm::actor_hit(const StoneContact &sc)
4110  {  {
4111      Turnstile_Pivot *pivot = get_pivot();      Turnstile_Pivot_Base *pivot = get_pivot();
4112    
4113      enum Action { ROTL, ROTR, stay };      enum Action { ROTL, ROTR, stay };
4114      static Action actions[4][4] = {      static Action actions[4][4] = {
# Line 4215  Turnstile_Arm::actor_hit(const StoneCont Line 4142  Turnstile_Arm::actor_hit(const StoneCont
4142      }      }
4143  }  }
4144    
4145  #endif // USE_IMPULSES  #endif // old code
   
 // void  
 // Turnstile_Pivot::animcb()  
 // {  
 //     Stone::init_model();  
 // }  
   
4146    
4147  DirectionBits  DirectionBits
4148  Turnstile_Pivot::arms_present()  Turnstile_Pivot_Base::arms_present()
4149  {  {
4150      DirectionBits arms = NODIRBIT;      DirectionBits arms = NODIRBIT;
4151      GridPos p = get_pos();      GridPos p = get_pos();
# Line 4241  Turnstile_Pivot::arms_present() Line 4161  Turnstile_Pivot::arms_present()
4161  }  }
4162    
4163  bool  bool
4164  Turnstile_Pivot::no_stone (int xoff, int yoff)  Turnstile_Pivot_Base::no_stone (int xoff, int yoff)
4165  {  {
4166      GridPos p = get_pos();      GridPos p = get_pos();
4167      p.x += xoff;      p.x += xoff;
# Line 4250  Turnstile_Pivot::no_stone (int xoff, int Line 4170  Turnstile_Pivot::no_stone (int xoff, int
4170  }  }
4171    
4172  void  void
4173  Turnstile_Pivot::remove_arms (DirectionBits arms)  Turnstile_Pivot_Base::remove_arms (DirectionBits arms)
4174  {  {
4175      GridPos p = get_pos();      GridPos p = get_pos();
4176      if (arms & NORTHBIT) KillStone (move (p, NORTH));      if (arms & NORTHBIT) KillStone (move (p, NORTH));
# Line 4260  Turnstile_Pivot::remove_arms (DirectionB Line 4180  Turnstile_Pivot::remove_arms (DirectionB
4180  }  }
4181    
4182  void  void
4183  Turnstile_Pivot::set_arm (Direction dir)  Turnstile_Pivot_Base::set_arms (DirectionBits arms)
4184    {
4185        GridPos p = get_pos();
4186        if (arms & NORTHBIT) set_arm(NORTH);
4187        if (arms & EASTBIT)  set_arm(EAST);
4188        if (arms & SOUTHBIT) set_arm(SOUTH);
4189        if (arms & WESTBIT)  set_arm(WEST);
4190    }
4191    
4192    void
4193    Turnstile_Pivot_Base::set_arm (Direction dir)
4194  {  {
4195      char *names[4] = { "st-turnstile-w",      char *names[4] = { "st-turnstile-w",
4196                         "st-turnstile-s",                         "st-turnstile-s",
# Line 4276  Turnstile_Pivot::set_arm (Direction dir) Line 4206  Turnstile_Pivot::set_arm (Direction dir)
4206  }  }
4207    
4208  bool  bool
4209  Turnstile_Pivot::rotate_left()  Turnstile_Pivot_Base::rotate_left()
4210  {  {
4211      DirectionBits arms = arms_present();      DirectionBits arms       = arms_present();
4212      bool can_rotate = true;      bool          can_rotate = true;
4213    
4214      if (arms & NORTHBIT) {      if (arms & NORTHBIT) {
4215          can_rotate &= no_stone(-1,-1);          can_rotate &= no_stone(-1,-1);
4216          if (! (arms & WESTBIT))          if (! (arms & WESTBIT)) can_rotate &= no_stone(-1,0);
             can_rotate &= no_stone(-1,0);  
4217      }      }
4218      if (arms & WESTBIT) {      if (arms & WESTBIT) {
4219          can_rotate &= no_stone(-1,+1);          can_rotate &= no_stone(-1,+1);
4220          if (! (arms & SOUTHBIT))          if (! (arms & SOUTHBIT)) can_rotate &= no_stone(0,+1);
             can_rotate &= no_stone(0,+1);  
4221      }      }
4222      if (arms & SOUTHBIT) {      if (arms & SOUTHBIT) {
4223          can_rotate &= no_stone(+1,+1);          can_rotate &= no_stone(+1,+1);
4224          if (! (arms & EASTBIT))          if (! (arms & EASTBIT)) can_rotate &= no_stone(+1,0);
             can_rotate &= no_stone(+1,0);  
4225      }      }
4226      if (arms & EASTBIT) {      if (arms & EASTBIT) {
4227          can_rotate &= no_stone(+1,-1);          can_rotate &= no_stone(+1,-1);
4228          if (! (arms & NORTHBIT))          if (! (arms & NORTHBIT)) can_rotate &= no_stone(0,-1);
             can_rotate &= no_stone(0,-1);  
4229      }      }
4230    
4231      if (can_rotate) {      if (can_rotate) {
4232  //        play_sound("rotate-left");  //        play_sound("rotate-left");
4233          play_sound("st-magic");          play_sound("st-magic");
4234          set_anim("st-turnstile-anim");  //         set_anim("st-turnstile-anim");
4235          remove_arms(arms);          set_anim(anim());
         if (arms & NORTHBIT) set_arm (WEST);  
         if (arms & EASTBIT) set_arm (NORTH);  
         if (arms & SOUTHBIT) set_arm (EAST);  
         if (arms & WESTBIT) set_arm (SOUTH);  
4236    
4237  #if defined(USE_IMPULSES)          remove_arms(arms);
4238            set_arms(rotate(arms, false));
4239          warpActorsInRange(false);          warpActorsInRange(false);
 #endif // USE_IMPULSES  
4240    
4241          display::GetStatusBar()->set_counter(player::IncMoveCounter());          display::GetStatusBar()->set_counter(player::IncMoveCounter());
4242      }      }
# Line 4322  Turnstile_Pivot::rotate_left() Line 4244  Turnstile_Pivot::rotate_left()
4244  }  }
4245    
4246  bool  bool
4247  Turnstile_Pivot::rotate_right()  Turnstile_Pivot_Base::rotate_right()
4248  {  {
4249      DirectionBits arms = arms_present();      DirectionBits arms       = arms_present();
4250      bool can_rotate = true;      bool          can_rotate = true;
4251    
4252      if (arms & NORTHBIT) {      if (arms & NORTHBIT) {
4253          can_rotate &= no_stone(+1,-1);          can_rotate &= no_stone(+1,-1);
4254          if (! (arms & EASTBIT))          if (! (arms & EASTBIT)) can_rotate &= no_stone(+1,0);
             can_rotate &= no_stone(+1,0);  
4255      }      }
4256      if (arms & WESTBIT) {      if (arms & WESTBIT) {
4257          can_rotate &= no_stone(-1,-1);          can_rotate &= no_stone(-1,-1);
4258          if (! (arms & NORTHBIT))          if (! (arms & NORTHBIT)) can_rotate &= no_stone(0,-1);
             can_rotate &= no_stone(0,-1);  
4259      }      }
4260      if (arms & SOUTHBIT) {      if (arms & SOUTHBIT) {
4261          can_rotate &= no_stone(-1,+1);          can_rotate &= no_stone(-1,+1);
4262          if (! (arms & WESTBIT))          if (! (arms & WESTBIT)) can_rotate &= no_stone(-1,0);
             can_rotate &= no_stone(-1,0);  
4263      }      }
4264      if (arms & EASTBIT) {      if (arms & EASTBIT) {
4265          can_rotate &= no_stone(+1,+1);          can_rotate &= no_stone(+1,+1);
4266          if (! (arms & SOUTHBIT))          if (! (arms & SOUTHBIT)) can_rotate &= no_stone(0,+1);
             can_rotate &= no_stone(0,+1);  
4267      }      }
4268    
4269      if (can_rotate) {      if (can_rotate) {
4270  //        play_sound("rotate-right");  //        play_sound("rotate-right");
4271          play_sound("st-magic");          play_sound("st-magic");
4272          set_anim("st-turnstile-anim");  //         set_anim("st-turnstile-anim");
4273          remove_arms(arms);          set_anim(anim());
         if (arms & NORTHBIT) set_arm (EAST);  
         if (arms & EASTBIT) set_arm (SOUTH);  
         if (arms & SOUTHBIT) set_arm (WEST);  
         if (arms & WESTBIT) set_arm (NORTH);  
4274    
4275  #if defined(USE_IMPULSES)          remove_arms(arms);
4276            set_arms(rotate(arms, true));
4277          warpActorsInRange(true);          warpActorsInRange(true);
 #endif // USE_IMPULSES  
4278    
4279          display::GetStatusBar()->set_counter(player::IncMoveCounter());          display::GetStatusBar()->set_counter(player::IncMoveCounter());
4280      }      }
# Line 4516  ObjectRepos::ObjectRepos() Line 4430  ObjectRepos::ObjectRepos()
4430      add_templ(new ThiefStone);      add_templ(new ThiefStone);
4431      add_templ(new TimerStone);      add_templ(new TimerStone);
4432    
4433      add_templ (new Turnstile_Pivot);      add_templ (new Turnstile_Pivot); // oxyd-comaptible
4434        add_templ (new Turnstile_Pivot_Green); // not oxyd-comaptible
4435      add_templ (new Turnstile_N);      add_templ (new Turnstile_N);
4436      add_templ (new Turnstile_S);      add_templ (new Turnstile_S);
4437      add_templ (new Turnstile_E);      add_templ (new Turnstile_E);

Legend:
Removed from v.1.61  
changed lines
  Added in v.1.62

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26