barge.cc

Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2000  Jeffrey S. Freedman
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #  include <config.h>
00027 #endif
00028 
00029 #include "barge.h"
00030 #include "gamewin.h"
00031 #include "gamemap.h"
00032 #include "actors.h"
00033 #include "Zombie.h"
00034 #include "citerate.h"
00035 #include "dir.h"
00036 #include "chunks.h"
00037 #include "objiter.h"
00038 #include "game.h"
00039 #include "databuf.h"
00040 #include "ucsched.h"
00041 
00042 using std::ostream;
00043 
00044 /*
00045  *  Rotate a point 90 degrees to the right around a point.
00046  *
00047  *  In cartesian coords with 'c' as center, the rule is:
00048  *    (newx, newy) = (oldy, -oldx)
00049  */
00050 
00051 inline Tile_coord Rotate90r
00052   (
00053   Tile_coord t,     // Tile to move.
00054   Tile_coord c      // Center to rotate around.
00055   )
00056   {
00057           // Get cart. coords. rel. to center.
00058   int rx = t.tx - c.tx, ry = c.ty - t.ty;
00059   return Tile_coord(c.tx + ry, c.ty + rx, t.tz);
00060   }
00061 
00062 /*
00063  *  Rotate a point 90 degrees to the left around a point.
00064  *
00065  *  In cartesian coords with 'c' as center, the rule is:
00066  *    (newx, newy) = (-oldy, oldx)
00067  */
00068 
00069 inline Tile_coord Rotate90l
00070   (
00071   Tile_coord t,     // Tile to move.
00072   Tile_coord c      // Center to rotate around.
00073   )
00074   {
00075           // Get cart. coords. rel. to center.
00076   int rx = t.tx - c.tx, ry = c.ty - t.ty;
00077   return Tile_coord(c.tx - ry, c.ty - rx, t.tz);
00078   }
00079 
00080 /*
00081  *  Rotate a point 180 degrees around a point.
00082  *
00083  *  In cartesian coords with 'c' as center, the rule is:
00084  *    (newx, newy) = (-oldx, -oldy)
00085  */
00086 
00087 inline Tile_coord Rotate180
00088   (
00089   Tile_coord t,     // Tile to move.
00090   Tile_coord c      // Center to rotate around.
00091   )
00092   {
00093           // Get cart. coords. rel. to center.
00094   int rx = t.tx - c.tx, ry = c.ty - t.ty;
00095   return Tile_coord(c.tx - rx, c.ty + ry, t.tz);
00096   }
00097 
00098 /*
00099  *  Figure tile where an object will be if it's rotated 90 degrees around
00100  *  a point counterclockwise, assuming its 'hot spot' 
00101  *  is at its lower-right corner.
00102  */
00103 
00104 inline Tile_coord Rotate90r
00105   (
00106   Game_window *gwin,
00107   Game_object *obj,
00108   int xtiles, int ytiles,   // Object dimensions.
00109   Tile_coord c      // Rotate around this.
00110   )
00111   {
00112           // Rotate hot spot.
00113   Tile_coord r = Rotate90r(obj->get_tile(), c);
00114           // New hotspot is what used to be the
00115           //   upper-right corner.
00116   r.tx = (r.tx + ytiles + c_num_tiles)%c_num_tiles;
00117   r.ty = (r.ty + c_num_tiles)%c_num_tiles;
00118   return r;
00119   }
00120 
00121 /*
00122  *  Figure tile where an object will be if it's rotated 90 degrees around
00123  *  a point, assuming its 'hot spot' is at its lower-right corner.
00124  */
00125 
00126 inline Tile_coord Rotate90l
00127   (
00128   Game_window *gwin,
00129   Game_object *obj,
00130   int xtiles, int ytiles,   // Object dimensions.
00131   Tile_coord c      // Rotate around this.
00132   )
00133   {
00134           // Rotate hot spot.
00135   Tile_coord r = Rotate90l(obj->get_tile(), c);
00136           // New hot-spot is old lower-left.
00137   r.ty = (r.ty + xtiles + c_num_tiles)%c_num_tiles;
00138   r.tx = (r.tx + c_num_tiles)%c_num_tiles;
00139   return r;
00140   }
00141 
00142 /*
00143  *  Figure tile where an object will be if it's rotated 180 degrees around
00144  *  a point, assuming its 'hot spot' is at its lower-right corner.
00145  */
00146 
00147 inline Tile_coord Rotate180
00148   (
00149   Game_window *gwin,
00150   Game_object *obj,
00151   int xtiles, int ytiles,   // Object dimensions.
00152   Tile_coord c      // Rotate around this.
00153   )
00154   {
00155           // Rotate hot spot.
00156   Tile_coord r = Rotate180(obj->get_tile(), c);
00157           // New hotspot is what used to be the
00158           //   upper-left corner.
00159   r.tx = (r.tx + xtiles + c_num_tiles)%c_num_tiles;
00160   r.ty = (r.ty + ytiles + c_num_tiles)%c_num_tiles;
00161   return r;
00162   }
00163 
00164 /*
00165  *  Swap dimensions.
00166  */
00167 
00168 inline void Barge_object::swap_dims
00169   (
00170   )
00171   {
00172   int tmp = xtiles;   // Swap dims.
00173   xtiles = ytiles;
00174   ytiles = tmp;
00175   }
00176 
00177 /*
00178  *  Get footprint in tiles.
00179  */
00180 
00181 Rectangle Barge_object::get_tile_footprint
00182   (
00183   )
00184   {
00185   Tile_coord pos = get_tile();
00186   int xts = get_xtiles(), yts = get_ytiles();
00187   Rectangle foot((pos.tx - xts + 1 + c_num_tiles)%c_num_tiles, 
00188     (pos.ty - yts + 1 + c_num_tiles)%c_num_tiles, xts, yts);
00189   return foot;
00190   }
00191 
00192 /*
00193  *  Set center.
00194  */
00195 
00196 inline void Barge_object::set_center
00197   (
00198   )
00199   {
00200   center = get_tile();
00201   center.tx = (center.tx - xtiles/2 + c_num_tiles)%c_num_tiles;
00202   center.ty = (center.ty - ytiles/2 + c_num_tiles)%c_num_tiles;
00203   }
00204 
00205 /*
00206  *  See if okay to rotate.
00207  +++++++++++Handle wrapping here+++++++++++
00208  */
00209 
00210 int Barge_object::okay_to_rotate
00211   (
00212   Tile_coord pos      // New position (bottom-right).
00213   )
00214   {
00215   int lift = get_lift();
00216           // Special case for carpet.
00217   int move_type = (lift >= 10) ? (MOVE_LEVITATE) : MOVE_ALL_TERRAIN;
00218           // Get footprint in tiles.
00219   Rectangle foot = get_tile_footprint();
00220   int xts = get_xtiles(), yts = get_ytiles();
00221           // Get where new footprint will be.
00222   Rectangle newfoot(pos.tx - yts + 1, pos.ty - xts + 1, yts, xts);
00223   int new_lift;
00224   if (newfoot.y < foot.y)   // Got a piece above the old one?
00225           // Check area.  (No dropping allowed.)
00226     if (Map_chunk::is_blocked(4, lift,
00227       newfoot.x, newfoot.y, newfoot.w, foot.y - newfoot.y,
00228         new_lift, move_type, 0) || new_lift != lift)
00229       return 0;
00230   if (foot.y + foot.h < newfoot.y + newfoot.h)
00231           // A piece below old one.
00232     if (Map_chunk::is_blocked(4, lift,
00233       newfoot.x, foot.y + foot.h, newfoot.w, 
00234       newfoot.y + newfoot.h - (foot.y + foot.h),
00235         new_lift, move_type, 0) || new_lift != lift)
00236       return 0;
00237   if (newfoot.x < foot.x)   // Piece to the left?
00238     if (Map_chunk::is_blocked(4, lift,
00239       newfoot.x, newfoot.y, foot.x - newfoot.x, newfoot.h,
00240         new_lift, move_type, 0) || new_lift != lift)
00241       return 0;
00242   if (foot.x + foot.w < newfoot.x + newfoot.w)
00243           // Piece to the right.
00244     if (Map_chunk::is_blocked(4, lift,
00245       foot.x + foot.w, newfoot.y,
00246       newfoot.x + newfoot.w - (foot.x + foot.w), newfoot.h,
00247         new_lift, move_type, 0) || new_lift != lift)
00248       return 0;
00249   return 1;
00250   }
00251 
00252 /*
00253  *  Delete.
00254  */
00255 
00256 Barge_object::~Barge_object
00257   (
00258   )
00259   {
00260   delete path;
00261   }
00262 
00263 /*
00264  *  Gather up all objects that appear to be on this barge.
00265  *  Also inits. 'center'.
00266  */
00267 
00268 void Barge_object::gather
00269   (
00270   )
00271   {
00272   if (!gmap->get_chunk_safely(get_cx(), get_cy()))
00273     return;     // Not set in world yet.
00274   ice_raft = false;   // We'll just detect it each time.
00275   objects.resize(perm_count); // Start fresh.
00276           // Get footprint in tiles.
00277   Rectangle foot = get_tile_footprint();
00278   int lift = get_lift();    // How high we are.
00279           // Go through intersected chunks.
00280   Chunk_intersect_iterator next_chunk(foot);
00281   Rectangle tiles;
00282   int cx, cy;
00283   bool si = Game::get_game_type() == SERPENT_ISLE;
00284   while (next_chunk.get_next(tiles, cx, cy))
00285     {
00286     Map_chunk *chunk = gmap->get_chunk(cx, cy);
00287     tiles.x += cx*c_tiles_per_chunk;
00288     tiles.y += cy*c_tiles_per_chunk;
00289     Game_object *obj;
00290     Object_iterator next(chunk->get_objects());
00291     while ((obj = next.get_next()) != 0)
00292       {   // Look at each object.
00293       if (obj == this)
00294         continue;
00295       if (obj->is_egg()) // don't pick up eggs
00296         continue;
00297       Tile_coord t = obj->get_tile();
00298       Shape_info& info = obj->get_info();
00299           // Above barge, within 5-tiles up?
00300       if (tiles.has_point(t.tx, t.ty) &&
00301           t.tz >= lift - 1 &&
00302           t.tz + info.get_3d_height() > lift && 
00303           (info.is_barge_part() || t.tz < lift + 5) &&
00304           obj->get_owner() != this)
00305         {
00306         objects.append(obj);
00307         if (si)
00308           {
00309           if (obj->get_shapenum() == 0x1f8)
00310             ice_raft = true;
00311           // Kludge for SI turtle.
00312           else if (obj->get_shapenum() == 0xd7)
00313             xtiles = 20;
00314           }
00315         }
00316       }
00317     }
00318   set_center();
00319           // Test for boat.
00320   Map_chunk *chunk = gmap->get_chunk_safely(
00321     center.tx/c_tiles_per_chunk, center.ty/c_tiles_per_chunk);
00322   if (boat == -1 && chunk != 0)
00323     {
00324     ShapeID flat = chunk->get_flat(center.tx%c_tiles_per_chunk,
00325             center.ty%c_tiles_per_chunk);
00326     if (flat.is_invalid())
00327       boat = 0;
00328     else
00329       {
00330       Shape_info& info = flat.get_info();
00331       boat = info.is_water();
00332       }
00333     }
00334   gathered = true;
00335   }
00336 
00337 /*
00338  *  Add a dirty rectangle for our current position.
00339  */
00340 
00341 void Barge_object::add_dirty
00342   (
00343   )
00344   {
00345   int x, y;     // Get lower-right corner.
00346   gwin->get_shape_location(this, x, y);
00347   int w = xtiles*c_tilesize, h = ytiles*c_tilesize;
00348   Rectangle box(x - w, y - h, w, h);
00349   box.enlarge(10);    // Make it a bit bigger.
00350   if (dir%2)      // Horizontal?  Stretch.
00351     { box.x -= 18; box.w += 36; }
00352   else
00353     { box.y -= 18; box.h += 36; }
00354   box = gwin->clip_to_win(box); // Intersect with screen.
00355   gwin->add_dirty(box);
00356   }
00357 
00358 /*
00359  *  Finish up moving all the objects by adding them back and deleting the
00360  *  saved list of positions.
00361  */
00362 
00363 void Barge_object::finish_move
00364   (
00365   Tile_coord *positions   // New positions.  Deleted when done.
00366   )
00367   {
00368   set_center();     // Update center.
00369   int cnt = objects.size(); // We'll move each object.
00370   for (int i = 0; i < cnt; i++) // Now add them back in new location.
00371     {
00372     Game_object *obj = get_object(i);
00373     if (i < perm_count) // Restore us as owner.
00374       obj->set_owner(this);
00375     obj->move(positions[i]);
00376     }
00377   delete [] positions;
00378           // Check for scrolling.
00379   gwin->scroll_if_needed(center);
00380   }
00381 
00382 /*
00383  *  Turn to face a given direction.
00384  */
00385 
00386 void Barge_object::face_direction
00387   (
00388   int ndir      // 0-7 0==North.
00389   )
00390   {
00391   ndir /= 2;      // Convert to 0-3.
00392   switch ((4 + ndir - dir)%4)
00393     {
00394   case 1:       // Rotate 90 degrees right.
00395     turn_right();
00396     break;
00397   case 2:
00398     turn_around();    // 180 degrees.
00399     break;
00400   case 3:
00401     turn_left();
00402     break;
00403   default:
00404     break;
00405     }
00406   }
00407 
00408 /*
00409  *  Travel towards a given tile.
00410  */
00411 
00412 void Barge_object::travel_to_tile
00413   (
00414   Tile_coord dest,    // Destination.
00415   int speed     // Time between frames (msecs).
00416   )
00417   {
00418   if (!path)
00419     path = new Zombie();
00420           // Set up new path.
00421   if (path->NewPath(get_tile(), dest, 0))
00422     {
00423     frame_time = speed;
00424           // Figure new direction.
00425     Tile_coord cur = get_tile();
00426     int dy = Tile_coord::delta(cur.ty, dest.ty),
00427         dx = Tile_coord::delta(cur.tx, dest.tx);
00428     int ndir = Get_direction4(-dy, dx);
00429     if (!ice_raft)    // Ice-raft doesn't rotate.
00430       face_direction(ndir);
00431     if (!in_queue())  // Not already in queue?
00432       gwin->get_tqueue()->add(Game::get_ticks(), this, 0L);
00433     }
00434   else
00435     frame_time = 0;   // Not moving.
00436   }
00437 
00438 /*
00439  *  Turn 90 degrees to the right.
00440  */
00441 
00442 void Barge_object::turn_right
00443   (
00444   )
00445   {
00446   add_dirty();      // Want to repaint old position.
00447           // Move the barge itself.
00448   Tile_coord rot = Rotate90r(gwin, this, xtiles, ytiles, center);
00449   if (!okay_to_rotate(rot)) // Check for blockage.
00450     return;
00451   Container_game_object::move(rot.tx, rot.ty, rot.tz);
00452   swap_dims();      // Exchange xtiles, ytiles.
00453   dir = (dir + 1)%4;    // Increment direction.
00454   int cnt = objects.size(); // We'll move each object.
00455           // But 1st, remove & save new pos.
00456   Tile_coord *positions = new Tile_coord[cnt];
00457   for (int i = 0; i < cnt; i++)
00458     {
00459     Game_object *obj = get_object(i);
00460     int frame = obj->get_framenum();
00461     Shape_info& info = obj->get_info();
00462     positions[i] = Rotate90r(gwin, obj, info.get_3d_xtiles(frame),
00463           info.get_3d_ytiles(frame), center);
00464     obj->remove_this(1);  // Remove object from world.
00465           // Set to rotated frame.
00466     obj->set_frame(obj->get_rotated_frame(1));
00467     obj->set_invalid(); // So it gets added back right.
00468     }
00469   finish_move(positions);   // Add back & del. positions.
00470   }
00471 
00472 /*
00473  *  Turn 90 degrees to the left.
00474  */
00475 
00476 void Barge_object::turn_left
00477   (
00478   )
00479   {
00480   add_dirty();      // Want to repaint old position.
00481           // Move the barge itself.
00482   Tile_coord rot = Rotate90l(gwin, this, xtiles, ytiles, center);
00483   if (!okay_to_rotate(rot)) // Check for blockage.
00484     return;
00485   Container_game_object::move(rot.tx, rot.ty, rot.tz);
00486   swap_dims();      // Exchange xtiles, ytiles.
00487   dir = (dir + 3)%4;    // Increment direction.
00488   int cnt = objects.size(); // We'll move each object.
00489           // But 1st, remove & save new pos.
00490   Tile_coord *positions = new Tile_coord[cnt];
00491   for (int i = 0; i < cnt; i++)
00492     {
00493     Game_object *obj = get_object(i);
00494     int frame = obj->get_framenum();
00495     Shape_info& info = obj->get_info();
00496     positions[i] = Rotate90l(gwin, obj, info.get_3d_xtiles(frame),
00497           info.get_3d_ytiles(frame), center);
00498     obj->remove_this(1);  // Remove object from world.
00499           // Set to rotated frame.
00500     obj->set_frame(obj->get_rotated_frame(3));
00501     obj->set_invalid(); // So it gets added back right.
00502     }
00503   finish_move(positions);   // Add back & del. positions.
00504   }
00505 
00506 /*
00507  *  Turn 180 degrees.
00508  */
00509 
00510 void Barge_object::turn_around
00511   (
00512   )
00513   {
00514   add_dirty();      // Want to repaint old position.
00515           // Move the barge itself.
00516   Tile_coord rot = Rotate180(gwin, this, xtiles, ytiles, center);
00517   Container_game_object::move(rot.tx, rot.ty, rot.tz);
00518   dir = (dir + 2)%4;    // Increment direction.
00519   int cnt = objects.size(); // We'll move each object.
00520           // But 1st, remove & save new pos.
00521   Tile_coord *positions = new Tile_coord[cnt];
00522   for (int i = 0; i < cnt; i++)
00523     {
00524     Game_object *obj = get_object(i);
00525     int frame = obj->get_framenum();
00526     Shape_info& info = obj->get_info();
00527     positions[i] = Rotate180(gwin, obj, info.get_3d_xtiles(frame),
00528           info.get_3d_ytiles(frame), center);
00529     obj->remove_this(1);  // Remove object from world.
00530           // Set to rotated frame.
00531     obj->set_frame(obj->get_rotated_frame(2));
00532     obj->set_invalid(); // So it gets added back right.
00533     }
00534   finish_move(positions);   // Add back & del. positions.
00535   }
00536 
00537 /*
00538  *  Ending 'barge mode'.
00539  */
00540 
00541 void Barge_object::done
00542   (
00543   )
00544   {
00545   gathered = false;   // Clear for next time.
00546   static int norecurse = 0; // Don't recurse on the code below.
00547   if (norecurse > 0)
00548     return;
00549   norecurse++;
00550   if (boat == 1)      // Look for sails on boat.
00551     {     // Pretend they were clicked on.
00552     int cnt = objects.size(); // Look for open sail.
00553     for (int i = 0; i < cnt; i++)
00554       {
00555       Game_object *obj = objects[i];
00556       if (obj->get_shapenum() == 251 &&
00557           (obj->get_framenum()&7) < 4)
00558         {
00559         obj->activate();
00560         break;
00561         }
00562       }
00563     }
00564   norecurse--;
00565   }
00566 
00567 /*
00568  *  Is it okay to land?
00569  */
00570 
00571 int Barge_object::okay_to_land
00572   (
00573   )
00574   {
00575   Rectangle foot = get_tile_footprint();
00576   int lift = get_lift();    // How high we are.
00577           // Go through intersected chunks.
00578   Chunk_intersect_iterator next_chunk(foot);
00579   Rectangle tiles;
00580   int cx, cy;
00581   while (next_chunk.get_next(tiles, cx, cy))
00582     {     // Check each tile.
00583     Map_chunk *chunk = gmap->get_chunk(cx, cy);
00584     for (int ty = tiles.y; ty < tiles.y + tiles.h; ty++)
00585       for (int tx = tiles.x; tx < tiles.x + tiles.w; tx++)
00586         if (chunk->get_highest_blocked(lift, tx, ty)
00587                 != -1)
00588           return (0);
00589     }
00590   return (1);
00591   }
00592 
00593 /*
00594  *  Handle a time event (for animation).
00595  */
00596 
00597 void Barge_object::handle_event
00598   (
00599   unsigned long curtime,    // Current time of day.
00600   long udata      // Ignored.
00601   )
00602   {
00603   if (!path || !frame_time || gwin->get_moving_barge() != this)
00604     return;     // We shouldn't be doing anything.
00605   Tile_coord tile;    // Get spot & walk there. 
00606           // Take two steps for speed.
00607   if (!path->GetNextStep(tile) || !step(tile))
00608     frame_time = 0;
00609           // But not when just starting.
00610   else if (!first_step && (!path->GetNextStep(tile) || !step(tile)))
00611     frame_time = 0;
00612   else
00613     gwin->get_tqueue()->add(curtime + frame_time, this, udata);
00614   first_step = false;   // After 1st, move 2 at a time.
00615   }
00616 
00617 /*
00618  *  Move to a new absolute location.
00619  */
00620 
00621 void Barge_object::move
00622   (
00623   int newtx, 
00624   int newty, 
00625   int newlift
00626   )
00627   {
00628   if (!gathered)      // Happens in SI with turtle.
00629     gather();
00630           // Want to repaint old position.
00631   add_dirty();
00632           // Get current location.
00633   Tile_coord old = get_tile();
00634           // Move the barge itself.
00635   Container_game_object::move(newtx, newty, newlift);
00636           // Get deltas.
00637   int dx = newtx - old.tx, dy = newty - old.ty, dz = newlift - old.tz;
00638   int cnt = objects.size(); // We'll move each object.
00639           // But 1st, remove & save new pos.
00640   Tile_coord *positions = new Tile_coord[cnt];
00641   int i;
00642   for (i = 0; i < cnt; i++)
00643     {
00644     Game_object *obj = get_object(i);
00645     Tile_coord ot = obj->get_tile();
00646           // Watch for world-wrapping.
00647     positions[i] = Tile_coord(
00648         (ot.tx + dx + c_num_tiles)%c_num_tiles,
00649         (ot.ty + dy + c_num_tiles)%c_num_tiles, 
00650         ot.tz + dz);
00651     obj->remove_this(1);  // Remove object from world.
00652     obj->set_invalid(); // So it gets added back right.
00653           // Animate a few shapes.
00654     int frame = obj->get_framenum();
00655     switch (obj->get_shapenum())
00656       {
00657     case 774:   // Cart wheel.
00658       obj->set_frame(((frame + 1)&3)|(frame&32));
00659       break;
00660     case 796:   // Draft horse.
00661       obj->set_frame(((frame + 4)&15)|(frame&32));
00662       break;
00663       }
00664     }
00665   finish_move(positions);   // Add back & del. positions.
00666   }
00667 
00668 /*
00669  *  Remove an object.
00670  */
00671 
00672 void Barge_object::remove
00673   (
00674   Game_object *obj
00675   )
00676   {
00677   obj->set_owner(0);
00678   obj->remove_this(1);    // Now remove from outside world.
00679   }
00680 
00681 /*
00682  *  Add an object.
00683  *
00684  *  Output: 0, meaning object should also be added to chunk.
00685  */
00686 
00687 bool Barge_object::add
00688   (
00689   Game_object *obj,
00690   bool dont_check,
00691   bool combine      // True to try to combine obj.  MAY
00692           //   cause obj to be deleted.
00693   )
00694   {
00695   objects.append(obj);    // Add to list.
00696   return (false);     // We want it added to the chunk.
00697   }
00698 
00699 /*
00700  *  Drop another onto this.
00701  *
00702  *  Output: 0 to reject, 1 to accept.
00703  */
00704 
00705 int Barge_object::drop
00706   (
00707   Game_object *obj
00708   )
00709   {
00710   return 0;     //++++++Later.
00711   }
00712 
00713 /*
00714  *  Paint at given spot in world.
00715  */
00716 
00717 void Barge_object::paint
00718   (
00719   )
00720   {
00721           // DON'T paint barge shape itself.
00722           // The objects are in the chunk too.
00723   if(gwin->paint_eggs)
00724     Container_game_object::paint();
00725   }
00726 
00727 /*
00728  *  Step onto an adjacent tile.
00729  *
00730  *  Output: 0 if blocked.
00731  *    Dormant is set if off screen.
00732  */
00733 
00734 int Barge_object::step
00735   (
00736   Tile_coord t,     // Tile to step onto.
00737   int       // Frame (ignored).
00738   )
00739   {
00740   if (!gathered)      // Happens in SI with turtle.
00741     gather();
00742   Tile_coord cur = get_tile();
00743           // Blocked? (Assume ht.=4, for now.)
00744   int move_type;
00745   if (cur.tz >= 10)
00746     {     // Definitely a carpet.
00747     move_type = MOVE_LEVITATE;
00748     boat = 0;
00749     }
00750   else if (boat) 
00751     {
00752     move_type = MOVE_SWIM;
00753           // Hawk's boat gets grounded in SI.
00754     if (Game::get_game_type() == SERPENT_ISLE)
00755       {
00756       int sx = cur.tx/c_tiles_per_schunk,
00757           sy = cur.ty/c_tiles_per_schunk;
00758       if (sx == 8 && sy == 9) // Hawk's ship.
00759         move_type |= MOVE_WALK;
00760       }
00761     }
00762   else move_type = MOVE_WALK;
00763           // No rising/dropping.
00764         if (Map_chunk::is_blocked(get_xtiles(), get_ytiles(), 
00765             4, cur, t, move_type, 0, 0))
00766     return (0);   // Done.
00767   move(t.tx, t.ty, t.tz);   // Move it & its objects.
00768           // Near an egg?
00769   Map_chunk *nlist = gmap->get_chunk(get_cx(), get_cy());
00770   nlist->activate_eggs(gwin->get_main_actor(), t.tx, t.ty, t.tz, 
00771             cur.tx, cur.ty);
00772   return (1);     // Add back to queue for next time.
00773   }
00774 
00775 /*
00776  *  Write out.
00777  */
00778 
00779 void Barge_object::write_ireg
00780   (
00781   DataSource *out
00782   )
00783   {
00784   unsigned char buf[13];    // 13-byte entry + length-byte.
00785   buf[0] = 12;
00786   unsigned char *ptr = &buf[1]; // To avoid confusion about offsets.
00787   write_common_ireg(ptr);   // Fill in bytes 1-4.
00788   ptr += 4;
00789           // Write size.
00790   *ptr++ = xtiles;
00791   *ptr++ = ytiles;
00792   *ptr++ = 0;     // Unknown.
00793           // Flags (quality).  Taking B3 to in-
00794           //   dicate barge mode.
00795   *ptr++ = (dir<<1) | ((gwin->get_moving_barge() == this)<<3);
00796   *ptr++ = 0;     // (Quantity).
00797   *ptr++ = (get_lift()&15)<<4;
00798   *ptr++ = 0;     // Data2.
00799   *ptr++ = 0;     // 
00800   out->write((char*)buf, sizeof(buf));
00801           // Write permanent objects.
00802   for (int i = 0; i < perm_count; i++)
00803     {
00804     Game_object *obj = get_object(i);
00805     obj->write_ireg(out);
00806     }
00807   out->write1(0x01);      // A 01 terminates the list.
00808           // Write scheduled usecode.
00809   Game_map::write_scheduled(out, this); 
00810   }
00811 
00812 // Get size of IREG. Returns -1 if can't write to buffer
00813 int Barge_object::get_ireg_size()
00814 {
00815   // These shouldn't ever happen, but you never know
00816   if (gwin->get_moving_barge() == this || Usecode_script::find(this))
00817     return -1;
00818 
00819   int total_size = 13;
00820 
00821   for (int i = 0; i < perm_count; i++)
00822   {
00823     Game_object *obj = get_object(i);
00824     int size = obj->get_ireg_size();
00825 
00826     if (size < 0) return -1;
00827 
00828     total_size += size;
00829   }
00830 
00831   total_size += 1;
00832 
00833   return total_size;
00834 }
00835 
00836 /*
00837  *  This is called after all elements have been read in and added.
00838  */
00839 
00840 void Barge_object::elements_read
00841   (
00842   )
00843   {
00844   perm_count = 0;     // So we don't get haystack!
00845   complete = true;
00846   }
00847 

Generated on Mon Jul 9 14:42:49 2007 for ExultEngine by  doxygen 1.5.1