actorio.cc

Go to the documentation of this file.
00001 /*
00002  *  actorio.cc - I/O for the Actor class.
00003  *
00004  *  Copyright (C) 2000-2001  The Exult Team
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 #  include <config.h>
00023 #endif
00024 
00025 #ifndef ALPHA_LINUX_CXX
00026 #  include <cstring>
00027 #endif
00028 #include "gamewin.h"
00029 #include "gamemap.h"
00030 #include "game.h"
00031 #include "monsters.h"
00032 #include "utils.h"
00033 #include "egg.h"
00034 #include "chunks.h"
00035 #include "schedule.h"
00036 #include "objiter.h"
00037 #include "databuf.h"
00038 #include "npctime.h"
00039 
00040 using std::ios;
00041 using std::cout;
00042 using std::endl;
00043 using std::istream;
00044 using std::ostream;
00045 
00046 /*
00047  *  Read in actor from a given file.
00048  */
00049 
00050 void Actor::read
00051   (
00052   DataSource* nfile,    // 'npc.dat', generally.
00053   int num,      // NPC #, or -1.
00054   bool has_usecode,   // 1 if a 'type1' NPC.
00055   bool& fix_unused    // Old savegame, so 'unused' isn't
00056           //   valid.  Possibly set here.
00057     //June9,02:  +++++Fix_unused should go away in a few months.
00058   )
00059   {
00060   npc_num = num;
00061 
00062   // This is used to get around parts of the files that we don't know
00063   // what the uses are. 'fix_first' is used fix issues in the originals
00064   // files that cause problems for the extra info we save.
00065   bool fix_first = Game::is_new_game();
00066           
00067   init();       // Clear rest of stuff.
00068   unsigned locx = nfile->read1(); // Get chunk/tile coords.
00069   unsigned locy = nfile->read1();
00070           // Read & set shape #, frame #.
00071   unsigned short shnum = nfile->read2();
00072 
00073   if (num == 0 && Game::get_game_type() != BLACK_GATE && 
00074             (shnum & 0x3ff) < 12)
00075     set_shape((shnum & 0x3ff) | 0x400);
00076   else
00077     set_shape(shnum & 0x3ff);
00078 
00079   set_frame(shnum >> 10);
00080   
00081   int iflag1 = nfile->read2();  // Inventory flag.
00082           // We're going to use these bits.
00083           // iflag1:0 == has_contents.
00084           // iflag1:1 == sched. usecode follows,
00085           //   possibly empty.
00086           // iflag1:2 == usecode # assigned by
00087           //   ES, so always use it.
00088   bool read_sched_usecode = !fix_first && (iflag1&2);
00089   if (!fix_first && (iflag1&4))
00090     usecode_assigned = true;
00091 
00092   int schunk = nfile->read1();  // Superchunk #.
00093   nfile->read1();     // Skip next byte.
00094   int usefun = nfile->read2();  // Get usecode function #.
00095   set_lift(usefun >> 12);   // Lift is high 4 bits.
00096   usecode = usefun & 0xfff;
00097 //  if (!npc_num)     // Avatar is always first.
00098 //    usecode = 0x400;
00099           // Need this for BG. (Not sure if SI.)
00100   if (npc_num >= 0 && npc_num < 256)
00101     usecode = 0x400 + npc_num;
00102           // Watch for new NPC's added.
00103   else if ((!has_usecode && !usecode_assigned && 
00104             usecode != 0x400 + npc_num) ||
00105       usecode == 0xfff)
00106     usecode = -1;   // Let's try this.
00107           // Guessing:  !!  (Want to get signed.)
00108   int health_val = static_cast<int>(static_cast<char>(nfile->read1()));
00109   set_property(static_cast<int>(Actor::health), health_val);
00110   nfile->skip(3); // Skip 3 bytes.
00111   int iflag2 = nfile->read2();  // The 'used-in-game' flag.
00112   if (iflag2 == 0 && num >= 0 && !fix_unused)
00113     {
00114     if (num == 0)   // Old (bad) savegame?
00115       fix_unused = true;
00116     else
00117       unused = true;
00118 #ifdef DEBUG
00119     cout << "NPC #" << num << " is unused" << endl;
00120 #endif
00121     }
00122 
00123   bool has_contents = fix_first ? (iflag1 && !unused) : (iflag1&1);
00124   // Read first set of flags
00125   const int rflags = nfile->read2();
00126   
00127   if ((rflags >> 0x7) & 1) set_flag (Obj_flags::asleep);
00128   if ((rflags >> 0x8) & 1) set_flag (Obj_flags::charmed);
00129   if ((rflags >> 0x9) & 1) set_flag (Obj_flags::cursed);
00130   if ((rflags >> 0xB) & 1) set_flag (Obj_flags::in_party);
00131   if ((rflags >> 0xC) & 1) set_flag (Obj_flags::paralyzed);
00132   if ((rflags >> 0xD) & 1) set_flag (Obj_flags::poisoned);
00133   if ((rflags >> 0xE) & 1) set_flag (Obj_flags::protection);
00134   if (!fix_first && ((rflags >> 0xF) & 1)) 
00135     set_flag (Obj_flags::dead);
00136 
00137   // Guess
00138   if (((rflags >> 0xA) & 1))
00139     set_flag (Obj_flags::on_moving_barge);
00140   alignment = (rflags >> 3)&3;
00141 
00142   // Unknown, using for is_temporary (only when not fix_first)
00143   if ((rflags >> 0x6) & 1 && !fix_first) set_flag (Obj_flags::is_temporary);
00144 
00145   /*  Not used by exult
00146 
00147   Unknown in U7tech
00148   if ((rflags >> 0x5) & 1) set_flag (Obj_flags::unknown);
00149 */
00150   
00151           // Get char. atts.
00152 
00153   // In BG - Strength (0-5), skin colour(6-7)
00154   // In SI - Strength (0-4), skin colour(5-6), freeze (7)
00155   int strength_val = nfile->read1();
00156 
00157   if (Game::get_game_type() == BLACK_GATE)
00158   {
00159     set_property(static_cast<int>(Actor::strength), strength_val & 0x3F);
00160 
00161     if (num == 0)
00162     {
00163       if (Game::get_avskin() >= 0 && Game::get_avskin() <= 3)
00164         set_skin_color (Game::get_avskin());
00165       else
00166         set_skin_color (((strength_val >> 6)-1) & 0x3);
00167     }
00168     else 
00169       set_skin_color (3);
00170   }
00171   else
00172   {
00173     set_property(static_cast<int>(Actor::strength), strength_val & 0x1F);
00174     
00175     if (num == 0)
00176     {
00177       if (Game::get_avskin() >= 0 && Game::get_avskin() <= 2)
00178         set_skin_color (Game::get_avskin());
00179       else
00180         set_skin_color ((strength_val >> 5) & 0x3);
00181     }
00182     else 
00183       set_skin_color (-1);
00184 
00185     if ((strength_val << 7) & 1) set_flag (Obj_flags::freeze);
00186   }
00187 
00188   if (is_dying() &&   // Now we know health, strength.
00189       npc_num > 0)    // DON'T do this for Avatar!
00190     set_flag(Obj_flags::dead);  // Fixes older savegames.
00191   // Dexterity
00192   set_property(static_cast<int>(Actor::dexterity), nfile->read1());
00193 
00194 
00195   // Intelligence (0-4), read(5), Tournament (6), polymorph (7)
00196   int intel_val = nfile->read1();
00197 
00198   set_property(static_cast<int>(Actor::intelligence), intel_val & 0x1F);
00199   if ((intel_val >> 5) & 1) set_flag (Obj_flags::read);
00200           // Tournament.
00201   if ((intel_val >> 6) & 1) 
00202     set_flag (Obj_flags::si_tournament);
00203   if ((intel_val >> 7) & 1) set_flag (Obj_flags::polymorph);
00204 
00205 
00206   // Combat skill (0-6), Petra (7)
00207   int combat_val = nfile->read1();
00208   set_property(static_cast<int>(Actor::combat), combat_val & 0x7F);
00209   if ((combat_val << 7) & 1) set_flag (Obj_flags::petra);
00210 
00211   schedule_type = nfile->read1();
00212   int amode = nfile->read1(); // Default attack mode
00213           // Just stealing 2 spare bits:
00214   combat_protected = (amode&(1<<4)) != 0;
00215   user_set_attack = (amode&(1<<5)) != 0;
00216   attack_mode = (Attack_mode) (amode&0xf);
00217 
00218   nfile->skip(3);   //Unknown
00219 
00220   // If NPC 0: MaxMagic (0-4), TempHigh (5-7) and Mana(0-4), TempLow (5-7)
00221   // Else: ID# (0-4) ???, TempHigh (5-7) and Mat (0), No Spell Casting (1), Zombie (3), TempLow (5-7)
00222   int magic_val = nfile->read1();
00223   int mana_val = nfile->read1();
00224 
00225   if (num == 0)
00226   {
00227     int magic = magic_val&0x1f, mana = mana_val&0x1f;
00228     set_property(static_cast<int>(Actor::magic), magic);
00229     
00230     // Need to make sure that mana is less than magic
00231     if (mana < magic)
00232       set_property(static_cast<int>(Actor::mana), mana);
00233     else
00234       set_property(static_cast<int>(Actor::mana), magic);
00235 
00236     set_flag (Obj_flags::met);
00237   }
00238   else
00239   {
00240     set_ident(magic_val&0x1F);
00241     if ((mana_val >> 0) & 1) set_flag (Obj_flags::met);
00242     if ((mana_val >> 1) & 1) set_flag(Obj_flags::no_spell_casting);
00243     if ((mana_val >> 2) & 1) set_flag (Obj_flags::si_zombie);
00244   }
00245 
00246 
00247   set_temperature (((magic_val >> 2) & 0x38) + ((mana_val >> 5) & 7));
00248 
00249 //  nfile->skip(1 );  // Index2???? (refer to U7tech.txt)
00250   face_num = nfile->read1();
00251   if (!face_num && npc_num > 0) // Fix older savegames.
00252     face_num = npc_num;
00253   nfile->skip(2 );  // Unknown
00254 
00255   set_property(static_cast<int>(Actor::exp), nfile->read4());
00256   set_property(static_cast<int>(Actor::training), nfile->read1());
00257 
00258 
00259   nfile->skip (2);  // Primary Attacker
00260   nfile->skip (2);  // Secondary Attacker
00261   oppressor = nfile->read2(); // Oppressor NPC id.
00262 
00263   nfile->skip (4);  //I-Vr ??? (refer to U7tech.txt)
00264 
00265   schedule_loc.tx = nfile->read2(); //S-Vr Where npc is supposed to 
00266   schedule_loc.ty = nfile->read2(); //be for schedule)
00267   
00268   // Type flags 2
00269   int tflags = nfile->read2();
00270 
00271   // First time round, all the flags are garbage
00272   if (fix_first)
00273     set_type_flags (1 << Actor::tf_walk);
00274   else
00275     set_type_flags (tflags);
00276 
00277 
00278   if (num == 0 && Game::get_avsex() == 0)
00279   {
00280     clear_type_flag (Actor::tf_sex);
00281   }
00282   else if (num == 0 && Game::get_avsex() == 1)
00283   {
00284     set_type_flag (Actor::tf_sex);
00285   }
00286   
00287 
00288   nfile->skip (5);  // Unknown
00289 
00290   next_schedule = nfile->read1(); // Acty ????? what is this??
00291 
00292   nfile->skip (1);  // SN ????? (refer to U7tech.txt)
00293   nfile->skip (2);  // V1 ????? (refer to U7tech.txt)
00294   nfile->skip (2);  // V2 ????? (refer to U7tech.txt)
00295 
00296   // 16 Bit Shape Numbers, allows for shapes > 1023
00297   shnum = nfile->read2();
00298   if (!fix_first && shnum)
00299   {
00300     if (GAME_BG && !sman->can_use_multiracial() && shnum > 1024 && npc_num == 0)
00301       set_actor_shape();
00302     else
00303       set_shape(shnum);   // 16 Bit Shape Number
00304 
00305     shnum = (sint16) nfile->read2();  // 16 Bit Polymorph Shape Number
00306     if (get_flag (Obj_flags::polymorph)) 
00307       {     // Try to fix messed-up flag.
00308       if (shnum != get_shapenum())
00309         set_polymorph(shnum);
00310       else
00311         clear_flag(Obj_flags::polymorph);
00312       }
00313   }
00314   else
00315   {
00316     nfile->skip (2);
00317     set_polymorph_default();
00318   }
00319 
00320   // More Exult stuff
00321   if (!fix_first)
00322   {
00323     uint32  f;
00324 
00325     // Flags
00326     f = nfile->read4();
00327     flags |= f;
00328     if (get_flag(Obj_flags::invisible)) /* Force timer. */
00329       need_timers()->start_invisibility();
00330 
00331     // SIFlags
00332     f = nfile->read2();
00333     siflags |= f;
00334 
00335     // Flags2 But don't set polymorph.
00336     bool polym = get_flag(Obj_flags::polymorph)!= false;
00337     f = nfile->read4();
00338     flags2 |= f;
00339     if (!polym && get_flag(Obj_flags::polymorph))
00340       clear_flag(Obj_flags::polymorph);
00341   }
00342   else
00343   {
00344     // Flags
00345     nfile->skip (4);
00346 
00347     // SIFlags
00348     nfile->skip (2);
00349 
00350     // Flags2 
00351     nfile->skip (4);
00352   }
00353 
00354   // Skip 15
00355   nfile->skip (15);
00356 
00357           // Get (signed) food level.
00358   int food_read = static_cast<int>(static_cast<char>(nfile->read1()));
00359   if (fix_first) food_read = 18;
00360   set_property(static_cast<int>(Actor::food_level), food_read);
00361 
00362   // Skip 7
00363   nfile->skip(7);
00364 
00365   char namebuf[17];
00366   nfile->read(namebuf, 16);
00367   
00368   for (int i = 0; i < 16; i++)
00369     if (namebuf[i] == 0) 
00370       i = 16;
00371     else if (namebuf[i] < ' ' || namebuf[i] >= 127)
00372     {
00373       namebuf[0] = 0;
00374       break;
00375     }
00376 
00377   namebuf[16] = 0;    // Be sure it's 0-delimited.
00378 //  cout << "Actor " << namebuf << " has alignment " << align << endl;
00379   
00380   if (num == 0 && Game::get_avname())
00381   {
00382     name = Game::get_avname();
00383   }
00384   else
00385     name = namebuf;   // Store copy of it.
00386 
00387           // Get abs. chunk. coords. of schunk.
00388   int scy = 16*(schunk/12);
00389   int scx = 16*(schunk%12);
00390   if (has_contents)   // Inventory?  Read.
00391     gwin->get_map()->read_ireg_objects(nfile, scx, scy, this);
00392   if (read_sched_usecode)   // Read in scheduled usecode.
00393     gwin->get_map()->read_special_ireg(nfile, this);
00394   int cx = locx >> 4;   // Get chunk indices within schunk.
00395   int cy = locy >> 4;
00396           // Get tile #'s.
00397   int tilex = locx & 0xf;
00398   int tiley = locy & 0xf;
00399   set_shape_pos(tilex, tiley);
00400   Map_chunk *olist = gmap->get_chunk_safely(scx + cx, scy + cy);
00401   set_invalid();      // Not in world yet.
00402   if (olist && !is_dead() &&  // Valid & alive?  Put into chunk list.
00403       !unused)
00404     {
00405     move((scx + cx)*c_tiles_per_chunk + tilex,
00406          (scy + cy)*c_tiles_per_chunk + tiley, get_lift());
00407 //    olist->add(this);
00408 //    switched_chunks(0, olist);  // Put in chunk's NPC list.
00409     }
00410   // Only do ready best weapon if we are in BG, this is the first time
00411   // and we are the Avatar or Iolo
00412   if (Game::get_game_type() == BLACK_GATE && Game::get_avname() && (num == 0 || num == 1))
00413     ready_best_weapon();
00414       
00415 #if defined(DEBUG) && 0
00416 
00417   cout << get_npc_num() << " Creating ";
00418 
00419   if (name.empty()) cout << get_name();
00420   else cout << name;
00421 
00422   cout << ", shape = " << 
00423     get_shapenum() <<
00424     ", frame = " << get_framenum() << ", usecode = " <<
00425         usefun << endl;
00426 
00427   cout << "Chunk coords are (" << scx + cx << ", " << scy + cy << "), lift is "
00428     << get_lift() << endl;
00429 
00430   cout << "Type Flags: ";
00431   if (get_type_flag(tf_fly)) cout << "fly ";
00432   if (get_type_flag(tf_swim)) cout << "swim ";
00433   if (get_type_flag(tf_walk)) cout << "walk ";
00434   if (get_type_flag(tf_ethereal)) cout << "ethereal ";
00435   if (get_type_flag(tf_in_party)) cout << "in party ";
00436   cout << endl;
00437 
00438 #endif
00439   }
00440 
00441 /*
00442  *  Write out to given file.
00443  */
00444 
00445 void Actor::write
00446   (
00447   DataSource* nfile     // Generally 'npc.dat'.
00448   )
00449   {
00450   int i;
00451   unsigned char buf4[4];    // Write coords., shape, frame.
00452 
00453   int old_shape = get_shapenum(); // Backup shape because we might change it
00454   set_shape( get_shape_real() );  // Change the shape out non polymorph one
00455   
00456   Game_object::write_common_ireg(buf4);
00457   nfile->write(reinterpret_cast<char*>(buf4), sizeof(buf4));
00458 
00459   set_shape( old_shape );   // Revert the shape to what it was
00460 
00461           // Inventory flag.
00462           // Bit0 = has_contents (our use).
00463           // Bit1 = our savegame, with sched.
00464           //   usecode script following this.
00465           // iflag1:2 == usecode # assigned by
00466           //   ES, so always use it.
00467   int iflag1 = objects.is_empty() ? 0 : 1;
00468   iflag1 |= 2;      // We're always doing write_scheduled()
00469   if (usecode_assigned)   // # assigned by EStudio?
00470     iflag1 |= 4;    // Set bit 2.
00471   nfile->write2(iflag1);
00472       // Superchunk #.
00473   nfile->write1((get_cy()/16)*12 + get_cx()/16);
00474   nfile->write1(0);     // Unknown.
00475           // Usecode.
00476   int usefun = get_usecode() & 0xfff;
00477           // Lift is in high 4 bits.
00478   usefun |= ((get_lift()&15) << 12);
00479   nfile->write2(usefun);
00480   nfile->write1(get_property(Actor::health));
00481   nfile->write1(0);     // Unknown 3 bytes.
00482   nfile->write2(0);
00483   nfile->write2(unused ? 0 : 1);  // Write 0 if unused.
00484 
00485   //Write first set of flags
00486   int iout = 0;
00487   
00488   if (get_flag (Obj_flags::asleep)) iout |= 1 << 0x7;
00489   if (get_flag (Obj_flags::charmed)) iout |= 1 << 0x8;
00490   if (get_flag (Obj_flags::cursed)) iout |= 1 << 0x9;
00491   if (get_flag (Obj_flags::in_party)) iout |= 1 << 0xB;
00492   if (get_flag (Obj_flags::paralyzed)) iout |= 1 << 0xC;
00493   if (get_flag (Obj_flags::poisoned)) iout |= 1 << 0xD;
00494   if (get_flag (Obj_flags::protection)) iout |= 1 << 0xE;
00495 
00496   // Guess
00497   if (get_flag (Obj_flags::on_moving_barge)) iout |= 1 << 0xA;
00498           // Alignment is bits 3-4.
00499 
00500   // Unknownm using for is_temp
00501   if (get_flag (Obj_flags::is_temporary)) iout |= 1 << 0x6;
00502 
00503   iout |= ((alignment&3) << 3);
00504 
00505   nfile->write2(iout);
00506   
00507           // Write char. attributes.
00508   iout = get_property(Actor::strength);
00509   if (Game::get_game_type() != BLACK_GATE && npc_num == 0) iout |= (get_skin_color () & 3) << 5;
00510   else if (npc_num == 0) iout |= ((get_skin_color()+1) & 3) << 6;
00511 
00512   if (get_flag (Obj_flags::freeze)) iout |= 1 << 7;
00513   nfile->write1(iout);
00514   
00515   nfile->write1(get_property(Actor::dexterity));
00516   
00517   iout = get_property(Actor::intelligence);
00518   if (get_flag (Obj_flags::read)) iout |= 1 << 5;
00519           // Tournament
00520   if (get_flag (Obj_flags::si_tournament)) iout |= 1 << 6;
00521   if (get_flag (Obj_flags::polymorph)) iout |= 1 << 7;
00522   nfile->write1(iout);
00523 
00524 
00525   iout = get_property(Actor::combat);
00526   if (get_flag (Obj_flags::petra)) iout |= 1 << 7;
00527   nfile->write1(iout);
00528   
00529   nfile->write1(get_schedule_type());
00530   unsigned char amode = attack_mode | 
00531     (combat_protected ? (1<<4) : 0) |
00532     (user_set_attack ? (1<<5) : 0);
00533   nfile->write1(amode);
00534   nfile->write1(0);   // Skip 3.
00535   nfile->write2(0);
00536 
00537   // Magic
00538   int mana_val = 0;
00539   int magic_val = 0;
00540   
00541   if (get_npc_num() == 0)
00542   {
00543     mana_val = get_property(static_cast<int>(Actor::mana));
00544     magic_val = get_property(static_cast<int>(Actor::magic));
00545   }
00546   else
00547   {
00548     magic_val = get_ident() & 0x1F;
00549     if (get_flag (Obj_flags::met)) mana_val |= 1;
00550     if (get_flag (Obj_flags::no_spell_casting)) mana_val |= 1 << 1;
00551     if (get_flag (Obj_flags::si_zombie)) mana_val |= 1 << 2;
00552   }
00553 
00554   // Tempertures
00555   mana_val |= (get_temperature () & 0x1F) << 5;
00556   magic_val |= (get_temperature () & 0x38) << 2;
00557 
00558   nfile->write1 (magic_val);
00559   nfile->write1 (mana_val);
00560 
00561   nfile->write1((face_num >= 0 && face_num <= 255) ? face_num : 0);
00562   nfile->write2(0);   // Skip 2
00563 
00564   nfile->write4(get_property(Actor::exp));
00565   nfile->write1(get_property(Actor::training));
00566       // 0x40 unknown.
00567 
00568   nfile->write2(0); // Skip 2*2
00569   nfile->write2(0);
00570   nfile->write2(oppressor); // Oppressor.
00571 
00572   nfile->write4(0); // Skip 2*2
00573   
00574   nfile->write2(schedule_loc.tx); //S-Vr Where npc is supposed to 
00575   nfile->write2(schedule_loc.ty); //be for schedule)
00576   //nfile->write4(0);
00577 
00578   nfile->write2(get_type_flags());  // Typeflags
00579   
00580   nfile->write4(0); // Skip 5
00581   nfile->write1(0);
00582 
00583   nfile->write1(next_schedule); // Acty ????? what is this??
00584 
00585   nfile->write1(0);   // Skip 1
00586   nfile->write2(0); // Skip 2
00587   nfile->write2(0); // Skip 2
00588 
00589   // 16 Bit Shapes
00590   if (get_flag (Obj_flags::polymorph))
00591   {
00592     nfile->write2(shape_save);  // 16 Bit Shape Num
00593     nfile->write2(get_shapenum());  // 16 Bit Polymorph Shape
00594   }
00595   else
00596   {
00597     nfile->write2(get_shapenum());  // 16 Bit Shape Num
00598     nfile->write2(0);   // 16 Bit Polymorph Shape
00599   }
00600 
00601   // Flags
00602   nfile->write4(flags);
00603 
00604   // SIFlags 
00605   nfile->write2(siflags);
00606 
00607   // flags2
00608   nfile->write4(flags2);
00609 
00610   // Skip 15
00611   for (i = 0; i < 15; i++)
00612     nfile->write1(0);
00613   
00614   // Food
00615   nfile->write1(get_property (Actor::food_level));
00616 
00617   // Skip 7
00618   for (i = 0; i < 7; i++)
00619     nfile->write1(0);
00620 
00621   char namebuf[17];   // Write 16-byte name.
00622   std::memset(namebuf, 0, 16);
00623   if (name.empty()) {
00624     std::string namestr = Game_object::get_name();
00625     std::strncpy(namebuf, namestr.c_str(), 16);
00626   } else
00627     std::strncpy(namebuf, name.c_str(), 16);
00628   nfile->write(namebuf, 16);
00629   write_contents(nfile);    // Write what he holds.
00630   namebuf[16] = 0;
00631           // Write scheduled usecode.
00632   Game_map::write_scheduled(nfile, this, true);
00633   }
00634 
00635 /*
00636  *  Write out to given file.
00637  */
00638 
00639 void Monster_actor::write
00640   (
00641   DataSource* nfile     // Generally 'npc.dat'.
00642   )
00643   {
00644   if (Actor::is_dead())   // Not alive?
00645     return;
00646   Actor::write(nfile);    // Now write.
00647   }
00648 
00649 /*
00650  *  Write Inventory
00651  */
00652 
00653 /*
00654  *  Write contents (if there is any).
00655  */
00656 
00657 void Actor::write_contents
00658   (
00659   DataSource* out
00660   )
00661 {
00662   if (!objects.is_empty())  // Now write out what's inside.
00663   {
00664     const int num_spots = static_cast<int>(sizeof(spots)/sizeof(spots[0]));
00665     sint8 i;
00666 
00667     for (i = 0; i < num_spots; ++i)
00668     {
00669       // Spot Increment
00670       if (spots[i])
00671       {
00672         // Write 2 byte index id
00673         out->write1(0x02);
00674         out->write2(static_cast<uint8>(i));
00675         spots[i]->write_ireg(out);
00676       }
00677     }
00678 
00679     Game_object *obj;
00680     Object_iterator next(objects);
00681 
00682     while ((obj = next.get_next()) != 0)
00683     {
00684       for (i = 0; i < num_spots; ++i)
00685         if (spots[i] == obj)
00686           break;
00687 
00688       if (i == num_spots)
00689       {
00690         // Write 2 byte index id (-1 = no slot)
00691         i = -1;
00692         out->write1(0x02);
00693         out->write2(static_cast<uint8>(i));
00694         obj->write_ireg(out);
00695       }
00696     }
00697     out->write1(0x01);    // A 01 terminates the list.
00698   }
00699 }
00700 

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