From 388cb04602b5fa9f0d0bae8768c6268bff9b8da9 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Mon, 4 May 2009 20:10:12 +0000 Subject: [PATCH] - Fixed the bug that prevented launching from the Finder - Wrote almost all the code for saving and loading a new-format party file, plus code to recognize the format of a file. (Windows saves should also be supported now) git-svn-id: http://openexile.googlecode.com/svn/trunk@50 4ebdad44-0ea0-11de-aab3-ff745001d230 --- osx/BoE.xcodeproj/project.pbxproj | 8 +- osx/Scenario Editor/BOEScen.rsrc | Bin 305906 -> 305906 bytes osx/Scenario Editor/scen.core.cpp | 10 +- osx/Scenario Editor/scen.townout.cpp | 4 +- osx/boe.actions.cpp | 13 +- osx/boe.fileio.cpp | 78 ++-- osx/boe.infodlg.cpp | 4 +- osx/boe.items.cpp | 4 +- osx/boe.main.cpp | 15 +- osx/boe.text.cpp | 2 +- osx/classes.h | 4 + osx/item.cpp | 107 ++++++ osx/item.h | 9 + osx/misc/dlgtool.cpp | 4 +- osx/misc/dlgutil.cpp | 13 +- osx/misc/dlgutil.h | 2 +- osx/misc/fileio.cpp | 519 ++++++++++++++++++++++++--- osx/misc/fileio.h | 2 +- osx/monster.h | 1 + osx/outdoors.cpp | 43 +++ osx/outdoors.h | 3 + osx/party.cpp | 258 +++++++++++++ osx/party.h | 7 +- osx/pc.cpp | 129 ++++++- osx/pc.h | 6 +- osx/regtown.h | 3 + osx/scenario.cpp | 2 +- osx/scenario.h | 4 +- osx/special.h | 1 + osx/talking.h | 1 + osx/terrain.h | 4 +- osx/tmpltown.h | 3 + osx/town.h | 1 + osx/universe.cpp | 125 +++++++ osx/universe.h | 6 +- osx/vehicle.h | 1 + 36 files changed, 1251 insertions(+), 145 deletions(-) diff --git a/osx/BoE.xcodeproj/project.pbxproj b/osx/BoE.xcodeproj/project.pbxproj index 357cbd18..6bdba020 100644 --- a/osx/BoE.xcodeproj/project.pbxproj +++ b/osx/BoE.xcodeproj/project.pbxproj @@ -394,7 +394,6 @@ 91E5C7A60F9F615400C21460 /* fileio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fileio.cpp; path = misc/fileio.cpp; sourceTree = ""; }; 91E5C7B60F9F619D00C21460 /* talking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = talking.h; sourceTree = ""; }; 91E5C7B70F9F619D00C21460 /* talking.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = talking.cpp; sourceTree = ""; }; - 91EBE8AA0F9A2BE1002356F2 /* scen.locutils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = scen.locutils.cpp; path = "Scenario Editor/scen.locutils.cpp"; sourceTree = ""; }; 91EBE8AC0F9A2BF2002356F2 /* scen.locutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scen.locutils.h; path = "Scenario Editor/scen.locutils.h"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -595,7 +594,6 @@ 91B3EEEA0F969BA700BF5B67 /* src */ = { isa = PBXGroup; children = ( - 91EBE8AA0F9A2BE1002356F2 /* scen.locutils.cpp */, 91B3EEEB0F969BA700BF5B67 /* scen.main.cpp */, 91B3EEEE0F969BA700BF5B67 /* scen.keydlgs.cpp */, 91B3EEEF0F969BA700BF5B67 /* scen.core.cpp */, @@ -1196,6 +1194,7 @@ OTHER_LDFLAGS = ( "-framework", Carbon, + "-lz", ); OTHER_LDFLAGS_QUOTED_FOR_TARGET_1 = "\"$(PROJECT_DIR)/misc/\""; PREBINDING = NO; @@ -1225,6 +1224,7 @@ OTHER_LDFLAGS = ( "-framework", Carbon, + "-lz", ); OTHER_LDFLAGS_QUOTED_FOR_TARGET_1 = "\"$(PROJECT_DIR)/misc/\""; PREBINDING = NO; @@ -1311,6 +1311,7 @@ OTHER_LDFLAGS = ( "-framework", Carbon, + "-lz", ); OTHER_LDFLAGS_QUOTED_FOR_TARGET_1 = "\"$(PROJECT_DIR)/misc/\""; PREBINDING = NO; @@ -1341,6 +1342,7 @@ OTHER_LDFLAGS = ( "-framework", Carbon, + "-lz", ); OTHER_LDFLAGS_QUOTED_FOR_TARGET_1 = "\"$(PROJECT_DIR)/misc/\""; PREBINDING = NO; @@ -1376,6 +1378,7 @@ OTHER_LDFLAGS = ( "-framework", Carbon, + "-lz", ); PREBINDING = NO; PRODUCT_NAME = "BoE Scenario Editor"; @@ -1411,6 +1414,7 @@ OTHER_LDFLAGS = ( "-framework", Carbon, + "-lz", ); PREBINDING = NO; PRODUCT_NAME = "BoE Scenario Editor"; diff --git a/osx/Scenario Editor/BOEScen.rsrc b/osx/Scenario Editor/BOEScen.rsrc index 93269f3b443869be69ffb129c29bade5aae24367..0850a69afc64aac9527743453df63b77f6809c2b 100644 GIT binary patch delta 2222 zcmXBUc~DnX6bJC{_4m+nG}Le>JGlX}h=_=&sECT@m>Mb}?r3FhV`fB*zn^=Wm6?-H zF^)4?W7e3XB&le)jG2-#6E2YpF{bA5hmkS4Mdy6q@6DU}oO928bKbr8{pv5YslU)> z-=44xFVqxG5I}3V5JD)&P|VaTQLk3$;Dy4=!$Zx`J~S}&bh#^cHK@T|y$bY7#UMC@ zt*#4OUl-=|ZlZUfv@Xm$zr1PNuH_-@FD);oV5{t}DBGrP$biTSf3h1xZ(Rho#r;bCRIWS0_sCQ#fgEfj|tl&U} zIu${)7oi@6m2{qZC|1$C)R|aK*Qv9x#vGQc9*ebfk$ODV(Wlhe*kEqjLY;&4bhf%> z9^PS4tijAuFX(M;rakFz1HuJSl}6XjN}|V^o8&+Q(b?ue33>=(Bj|4tBZ$9AA4Gzn z_fvE!`l^@F-yv0fkv@dMg2Z(CFf!D;=pzV@67+e3K^exX7tlvBL0v^3!(>5H8vQ+H zscYzR%oFsjqmQFNkbH+efwh8u<@6%W`6f^DM52GI8pT(yD0>o{=T zJj{Qa-%%_W@h|f?EI+c4{==LVN8h6N()H#sx9PvJQ!t@9eb4d}Hq-ym^>l+eh{+Ea z+_!-#sq_PSC;bqg3vz1cN7y5n=1+cXHPhL&*Va6*LdzvfcbuiDl!hA<_ z{w8zK>%^dj1D(zDtLbO(jo`H)lbRS$56mV6%B-9F4aL>HH)?9EAYm#wG5aN=0 z{ZJ=Z={J;uzXYp%_eX z`Hl9l`U;QvX)afAp4$Gg6bqX-@PlivX#DR&%b(_?qj~5K+km_=y|G5 zXVB9IYW*gn%r_n}-^+ZvfsQlRouw1Z^@Vgl^L@Y3DdvZMKE?bfjWxs64*nKrn7#4L z2ZvkmWEF!E=9VYuk>=Jt=~3o(d9)oa*QuBuWA6M3J<%L_m(Dgn>pyd{IjSr3Ip*kG z`XzHr3eTUH;64%;JB|ZsHW1f~jyA`4r(?`XZD>2yE+w0O&TSW$x`>Xq{NN0Fp4%gC z_;$0`+wB!Qv-%5kx0(@^^w7qj2BS7Jh_!(+|Itb27f#VHy944T`P)(LO2tj_4_$w& znOe)5uI4=djc>a$aWi%>|ED`HE`JSu$DJ1Us^4g;)h}!gbkdG`Td?Gs6?r|~IdN|k Um`iuP=T)}kK`t%$)GG}CAN5Buv;Y7A delta 2159 zcmW;Mdr;Ly6bJCLp2f_;tUF{r$WA^{K@ky=@QsRQrh-a{Z!|L>3|x$i@%q4LRHRHY z#W>7FjhbVO-UJm5l`&E(W4QN{xBkZQS?1~XYQTP`JLUpXZN?e%~w3lS3D($ z1NI%`*S0+f*!dv9;M)OTE`1PSFKp=ONthjO50zGA+tJ2H_$0TtGoV3Fmi6A`uEngbUbD{e^}E!G-({4H62w0~hfL8Y(pG8Tbg7(g@fKmv9+H z!&hNHpQJHD;bY-4K1CDZVz``7lW(ff@JgkPe zKmMDFgl2b!L%2ns&(4EG`5)(IIGkHyAI*D=Ad(+xVtzCn&5xan;8=b_UkD{(#u?+e zjSdSf)Xs7IueMpFMaSFc)k{3^42#zX?}2C87o4#|8Hu*LdU-vZWP7MnbKw-9?dbyj zgC(|?di8ZU)xJny3%#8Nud=<#FSI5YUSs>yNmx6l*@1Kx))n&F5V|0=7JDTl%MPL{ z_!yjR2UE4s`a*cK9YQriX#(fiFsg-p2N3MC;Z!G-o&)FF;dDbNOIIb&M$m1cO?YP+ z`F4aB=UWFC*hso7v^fthv?HlWXp0t9WTWUWp{?p-JBnI`wza|sZ8SX*+NrB`1Q!7b z?a}c|Y>dwY2z|H;f#1GjItzUq3YXbfgA=j$EL?8KnjoQ1s^AJc-t-XKKLf6`6HITR z195PbooMPHp3D??JO^DD}I{P}>Y;bByx_NvF8TGWqL?TE- z;ug=<4khJq179*RLdV15M!syu!P#&VSDQGv4!+Mnm}x?OEuw|p3i(UmhdfTlIrSUd z#^LJIeoumzc(l5FHEcNncaqSVWCWc!QWIwb;Xv-IzR&>hv zofnunLYKC}!JJ}nL@$TK!u_>k;q_PBrff)#t;r_>PW$<072M!__y3!b!Zse1!dU8@G}-g$HQjwidC32dW#|;8Y&0 zZfu2Daj3fK61;|os+%{$X*^Q>NDKAyeDxE3p2bn>wiq~@C%}f%;LSWyZD+wb?3<*) z)3pe8@nm(E^KdRtQ9m~T&f}@-ZYgj+>*g{&3*iEuuI}|IT*!0O!S~@JPE^07V;1u~ z^}s&xK~7SKB*RDe4fUWX-2dJZJJjqGGh`<0=NL_d4u;D(L><--F6Tk&2wXDW3f5h1 zq7vase%Ta=iN>+?R&kg6q-pKt?k!#_9XPov^-3MG#r)8PIiE~EG9Dx4lFJHz}9rZ OM$QZ>&HBu4?D{_gTFplQ diff --git a/osx/Scenario Editor/scen.core.cpp b/osx/Scenario Editor/scen.core.cpp index 42780bbd..be27f1d7 100644 --- a/osx/Scenario Editor/scen.core.cpp +++ b/osx/Scenario Editor/scen.core.cpp @@ -1464,8 +1464,8 @@ void put_item_info_in_dlog() { cdsin(818,52,store_which_item); CDST(818,2,store_item.full_name); CDST(818,3,store_item.name); - if (store_item.graphic_num >= 150) - csp(818,49,store_item.graphic_num % 150,PICT_CUSTOM + PICT_ITEM); + if (store_item.graphic_num >= 1000) // was 150 + csp(818,49,store_item.graphic_num % 1000,PICT_CUSTOM + PICT_ITEM); else csp(818,49,/*1800 + */store_item.graphic_num,PICT_ITEM); CDSN(818,4,store_item.graphic_num); cd_set_led_range(818,18,45,store_item.variety); @@ -1567,10 +1567,8 @@ void edit_item_type_event_filter (short item_hit) { case 56: if (save_item_info() == false) break; i = choose_graphic(/*1800,1922*/0,PICT_N_ITEM,store_item.graphic_num/* + 1800*/,PICT_ITEM,818); - if (i >= 0) { - store_item.graphic_num = i - 1800; - } - else break; + if (i < 0) break; + store_item.graphic_num = i; put_item_info_in_dlog(); break; case 69: diff --git a/osx/Scenario Editor/scen.townout.cpp b/osx/Scenario Editor/scen.townout.cpp index e9d42549..9e667e9b 100644 --- a/osx/Scenario Editor/scen.townout.cpp +++ b/osx/Scenario Editor/scen.townout.cpp @@ -321,8 +321,8 @@ void put_placed_item_in_dlog() { else cd_set_led(836,14,0); i = scenario.scen_items[store_placed_item.code].graphic_num; - if (i >= 150) // was 1000 - csp(836,4,i % 150,PICT_CUSTOM + PICT_ITEM); + if (i >= 1000) // was 1000, then was 150 + csp(836,4,i % 1000,PICT_CUSTOM + PICT_ITEM); else csp(836,4,/*1800 + */i,PICT_ITEM); } bool get_placed_item_in_dlog() { diff --git a/osx/boe.actions.cpp b/osx/boe.actions.cpp index 00e46d1f..e4f8e618 100644 --- a/osx/boe.actions.cpp +++ b/osx/boe.actions.cpp @@ -733,10 +733,10 @@ bool handle_action(EventRecord event) destination.x += cur_direction.x; destination.y += cur_direction.y; - for (i = 0; i < 6; i++) // debug - if (ADVEN[i].exp_adj != 100) { - ASB("Error: Flag 1"); - } +// for (i = 0; i < 6; i++) // debug +// if (ADVEN[i].exp_adj != 100) { +// ASB("Error: Flag 1"); +// } // Begin: Moving if (overall_mode == MODE_COMBAT) { @@ -2478,8 +2478,9 @@ void start_new_game() save_party(file); party_in_memory = true; } catch(no_file_chosen){} - - } + + party_in_memory = true; +} location get_cur_direction(Point the_point) { diff --git a/osx/boe.fileio.cpp b/osx/boe.fileio.cpp index ef56f210..828a9fa7 100644 --- a/osx/boe.fileio.cpp +++ b/osx/boe.fileio.cpp @@ -105,25 +105,13 @@ string progDir; CInfoPBRec myCPB; GWorldPtr spec_scen_g = NULL; ResFileRefNum mainRef, graphicsRef, soundRef; - +#include +ofstream flog("bladeslog.txt"); void init_directories() { short error; //Str255 folder_name = "\p::::Blades of Exile Scenarios"; -// HGetVol((StringPtr) start_name,&start_volume,&start_dir); -// HGetVol((StringPtr) data_name,&data_volume,&data_dir); -// HOpenResFile(start_volume,start_dir,"\p::::bladesofexile.rsrc",1); -// error = HOpenResFile(start_volume,start_dir,"\p::::Scenario Editor:Blades of Exile Sounds",1); -// if (ResError() != 0) { -// Alert(984,NIL); -// ExitToShell(); -// } -// error = HOpenResFile(start_volume,start_dir,"\p::::Scenario Editor:Blades of Exile Graphics",1); -// if (ResError() != 0) { -// Alert(984,NIL); -// ExitToShell(); -// } char cPath[768]; CFBundleRef mainBundle=CFBundleGetMainBundle(); CFURLRef graphicsURL = CFBundleCopyResourceURL(mainBundle,CFSTR("bladesofexile.rsrc"),CFSTR(""),NULL); @@ -133,35 +121,10 @@ void init_directories() FSPathMakeRef((UInt8*)cPath, &gRef, false); error = FSOpenResourceFile(&gRef, 0, NULL, fsRdPerm, &mainRef); if (error != noErr) { - printf("Error! Main resource file not found.\n"); + flog << "Error! Main resource file not found.\n"; + flog << "\t(Error " << (long)error << " occurred.)\n"; ExitToShell(); } - char *path = "Scenario Editor/Blades of Exile Graphics"; - error = FSPathMakeRef((UInt8*) path, &gRef, false); - error = FSOpenResourceFile(&gRef, 0, NULL, fsRdPerm, &graphicsRef); - if (error != noErr) { - //SysBeep(1); - printf("Error! File Blades of Exile Graphics not found.\n"); - ExitToShell(); - } - path = "Scenario Editor/Blades of Exile Sounds"; - FSPathMakeRef((UInt8*) path, &sRef, false); - error = FSOpenResourceFile(&sRef, 0, NULL, fsRdPerm, &soundRef); - if (error != noErr) { - //SysBeep(1); - printf("Error! File Blades of Exile Sounds not found.\n"); - ExitToShell(); - } - - // now I generate the directory ID of the folder which contains the scenarios - // code copied from Mac Prog FAQ book -// myCPB.dirInfo.ioNamePtr = folder_name; -// myCPB.dirInfo.ioVRefNum = start_volume; -// myCPB.dirInfo.ioFDirIndex = 0; -// myCPB.dirInfo.ioDrDirID = start_dir; -// error = PBGetCatalogInfoSync(&myCPB); // false means not async -// -// scen_dir = myCPB.dirInfo.ioDrDirID; CFStringRef progURL = CFURLCopyFileSystemPath(CFBundleCopyBundleURL(mainBundle), kCFURLPOSIXPathStyle); const char* tmp = CFStringGetCStringPtr(progURL, kCFStringEncodingASCII);//kCFStringEncodingUTF8); @@ -179,6 +142,39 @@ void init_directories() size_t last_slash = progDir.find_last_of('/'); progDir.erase(last_slash); std::cout<= 150) - csp(998,1,s_i.graphic_num - 150,PICT_CUSTOM + PICT_ITEM); + if (s_i.graphic_num >= 1000) // was 150 + csp(998,1,s_i.graphic_num - 1000,PICT_CUSTOM + PICT_ITEM); else csp(998,1,s_i.graphic_num,PICT_ITEM); // id? magic? diff --git a/osx/boe.items.cpp b/osx/boe.items.cpp index 39b990d0..2e1d82dc 100644 --- a/osx/boe.items.cpp +++ b/osx/boe.items.cpp @@ -904,8 +904,8 @@ void put_item_graphics() sprintf ((char *) message, "%s", (item.is_ident()) ? (char *) item.full_name : (char *) item.name); csit(987,21 + i * 4,(char *) message); - if (item.graphic_num >= 150) - csp(987,20 + i * 4,/*3000 + 2000 + */item.graphic_num - 150,PICT_CUSTOM + PICT_ITEM); + if (item.graphic_num >= 1000) // was 150 + csp(987,20 + i * 4,/*3000 + 2000 + */item.graphic_num - 1000,PICT_CUSTOM + PICT_ITEM); else csp(987,20 + i * 4,/*4800 + */item.graphic_num,PICT_ITEM); get_item_interesting_string(item,(char *) message); csit(987,22 + i * 4,(char *) message); diff --git a/osx/boe.main.cpp b/osx/boe.main.cpp index 76759253..0f752ee7 100644 --- a/osx/boe.main.cpp +++ b/osx/boe.main.cpp @@ -170,7 +170,6 @@ int main(void) { //data_store = (piles_of_stuff_dumping_type *) NewPtr(sizeof(piles_of_stuff_dumping_type)); start_time = TickCount(); - printf("Starting initialization..."); Initialize(); #ifdef EXILE_BIG_GUNS //main_dialog_UPP = NewModalFilterProc(cd_event_filter); @@ -274,10 +273,11 @@ void Initialize(void) Str255 tit = " "; /* Initialize all the needed managers. */ - InitCursor(); + //InitCursor(); + + + //GetKeys(key_state); - GetKeys(key_state); - // // To make the Random sequences truly random, we need to make the seed start // at a different number. An easy way to do this is to put the current time @@ -296,9 +296,10 @@ void Initialize(void) // BitMap bmap; GetQDGlobalsScreenBits(&bmap); - windRect = bmap.bounds; + SetRect(&windRect,bmap.bounds.left,bmap.bounds.top,bmap.bounds.right,bmap.bounds.bottom); + //windRect = bmap.bounds; - find_quickdraw(); + //find_quickdraw(); init_directories(); // stored_key = open_pref_file(); @@ -1148,7 +1149,7 @@ void find_quickdraw() { } } else { - SysBeep(2); + SysBeep(50); ExitToShell(); } } diff --git a/osx/boe.text.cpp b/osx/boe.text.cpp index 6b3e6453..5b5c60f0 100644 --- a/osx/boe.text.cpp +++ b/osx/boe.text.cpp @@ -1056,7 +1056,7 @@ void get_ter_name(char *str,unsigned char num) if ((num == 90) && ((is_out()) || (is_town()) || ((is_combat()) && (which_combat_type == 1)))) sprintf((char *) store_name,"Pit"); else { - strcpy((char *) store_name,(char *) scenario.ter_names[num]); + strcpy((char *) store_name,(char *) scenario.ter_types[num].name.c_str()); } strcpy((char *) str,(char *) store_name); } diff --git a/osx/classes.h b/osx/classes.h index 834b86cd..3b18ba05 100644 --- a/osx/classes.h +++ b/osx/classes.h @@ -8,6 +8,10 @@ * */ +#include +#include +using namespace std; + #include "location.h" #include "terrain.h" #include "vehicle.h" diff --git a/osx/item.cpp b/osx/item.cpp index d9d4f810..bb43e8a7 100644 --- a/osx/item.cpp +++ b/osx/item.cpp @@ -297,6 +297,10 @@ cItemRec& cItemRec::operator = (legacy::item_record_type& old){ type = (eWeapType) old.type; magic_use_type = old.magic_use_type; graphic_num = old.graphic_num; + if(graphic_num >= 150) // custom item graphic + graphic_num += 850; + else if(graphic_num == 59) // duplicate mushroom graphic + graphic_num = 64; ability = (eItemAbil) old.ability; ability_strength = old.ability_strength; type_flag = old.type_flag; @@ -314,3 +318,106 @@ cItemRec& cItemRec::operator = (legacy::item_record_type& old){ reserved2 = old.reserved2; return *this; } + +void cItemRec::writeTo(ostream& file, string prefix){ + file << prefix << "VARIETY " << variety << endl; + file << prefix << "LEVEL " << item_level << endl; + file << prefix << "AWKWARD " << awkward << endl; + file << prefix << "BONUS " << bonus << endl; + file << prefix << "PROT " << protection << endl; + file << prefix << "CHARGES " << charges << endl; + file << prefix << "WEAPON " << type << endl; + file << prefix << "USE " << magic_use_type << endl; + file << prefix << "ICON " << graphic_num << endl; + file << prefix << "ABILITY " << ability << endl; + file << prefix << "ABILSTR " << ability_strength << endl; + file << prefix << "TYPE " << type_flag << endl; + file << prefix << "ISSPEC " << is_special << endl; + file << prefix << "VALUE " << value << endl; + file << prefix << "WEIGHT " << weight << endl; + file << prefix << "SPEC " << special_class << endl; + file << prefix << "AT " << item_loc.x << ' ' << item_loc.y << endl; + file << prefix << "FULLNAME " << full_name << endl; + file << prefix << "NAME " << name << endl; + file << prefix << "TREASURE " << treas_class << endl; + if(is_ident()) file << prefix << "IDENTIFIED" << endl; + if(is_property()) file << prefix << "PROPERTY" << endl; + if(is_magic()) file << prefix << "MAGIC" << endl; + if(is_contained()) file << prefix << "CONTAINED" << endl; + if(is_cursed()) file << prefix << "CURSED" << endl; + if(is_concealed()) file << prefix << "CONCEALED" << endl; + if(is_enchanted()) file << prefix << "ENCHANTED" << endl; +} + +void cItemRec::readAttrFrom(string cur, istream& sin){ + if(cur == "VARIETY") sin >> variety; + else if(cur == "LEVEL") sin >> item_level; + else if(cur == "AWKWARD") sin >> awkward; + else if(cur == "BONUS") sin >> bonus; + else if(cur == "PROT") sin >> protection; + else if(cur == "CHARGES") sin >> charges; + else if(cur == "WEAPON") sin >> type; + else if(cur == "USE") sin >> magic_use_type; + else if(cur == "ICON") sin >> graphic_num; + else if(cur == "ABILITY") sin >> ability; + else if(cur == "ABILSTR") sin >> ability_strength; + else if(cur == "TYPE") sin >> type_flag; + else if(cur == "ISSPEC") sin >> is_special; + else if(cur == "VALUE") sin >> value; + else if(cur == "WEIGHT") sin >> weight; + else if(cur == "SPEC") sin >> special_class; + else if(cur == "AT") sin >> item_loc.x >> item_loc.y; + else if(cur == "FULLNAME"){ + getline(sin,cur); + strcpy(full_name,cur.c_str()); + }else if(cur == "NAME"){ + getline(sin,cur); + strcpy(name,cur.c_str()); + } + else if(cur == "TREASURE") sin >> treas_class; + else if(cur == "IDENTIFIED") set_ident(true); + else if(cur == "PROPERTY") set_property(true); + else if(cur == "MAGIC") set_magic(true); + else if(cur == "CONTAINED") set_contained(true); + else if(cur == "CURSED") set_cursed(true); + else if(cur == "CONCEALED") set_concealed(true); + else if(cur == "ENCHANTED") set_enchanted(true); +} + +ostream& operator << (ostream& out, eWeapType& e){ + out << (int) e; +} + +ostream& operator << (ostream& out, eItemType& e){ + out << (int) e; +} + +ostream& operator << (ostream& out, eItemAbil& e){ + out << (int) e; +} + +istream& operator >> (istream& in, eWeapType& e){ + int i; + in >> i; + if(i > 0 && i < 4) + e = (eWeapType) i; + else e = ITEM_NOT_MELEE; +} + +istream& operator >> (istream& in, eItemType& e){ + int i; + in >> i; + if(i > 0 && i < 28) + e = (eItemType) i; + else e = ITEM_TYPE_NO_ITEM; +} + +istream& operator >> (istream& in, eItemAbil& e){ + int i; + in >> i; + if((i > 0 && i < 15) || (i > 29 && i < 63) || + (i > 69 && i < 95) || (i > 109 && i < 136) || + (i > 149 && i < 162) || (i > 169 && i < 177)) + e = (eItemAbil) i; + else e = ITEM_NO_ABILITY; +} diff --git a/osx/item.h b/osx/item.h index f049f259..3c7ce52d 100644 --- a/osx/item.h +++ b/osx/item.h @@ -230,8 +230,17 @@ public: cItemRec(); cItemRec(long preset); cItemRec& operator = (legacy::item_record_type& old); + void writeTo(ostream& file, string prefix = ""); + void readAttrFrom(string cur, istream& sin); }; +ostream& operator << (ostream& out, eWeapType& e); +ostream& operator << (ostream& out, eItemType& e); +ostream& operator << (ostream& out, eItemAbil& e); +istream& operator >> (istream& in, eWeapType& e); +istream& operator >> (istream& in, eItemType& e); +istream& operator >> (istream& in, eItemAbil& e); + /* typedef struct { short variety, item_level; diff --git a/osx/misc/dlgtool.cpp b/osx/misc/dlgtool.cpp index 99a4e426..d544bbc5 100644 --- a/osx/misc/dlgtool.cpp +++ b/osx/misc/dlgtool.cpp @@ -27,7 +27,7 @@ extern bool modeless_exists[18]; extern DialogPtr modeless_dialogs[18]; extern PixPatHandle bg[]; -extern short geneva_font_num, sword_curs; +extern short geneva_font_num;//, sword_curs; GWorldPtr dlg_buttons_gworld[NUM_BUTTONS][2]; map dlg_gworlds; @@ -151,7 +151,7 @@ short cd_create_dialog(short dlog_num,WindowPtr parent){ ForeColor(blackColor); BackColor(whiteColor); untoast_dialog(); - set_cursor(sword_curs); + //set_cursor(sword_curs); return 0; } diff --git a/osx/misc/dlgutil.cpp b/osx/misc/dlgutil.cpp index 945de929..ce9c55ea 100644 --- a/osx/misc/dlgutil.cpp +++ b/osx/misc/dlgutil.cpp @@ -193,16 +193,19 @@ short cd_create_custom_dialog(WindowPtr parent, Str255 strs[6],short pic_num,sho return 0; } -void oops_error(short error, short code){ - Str255 error_str; +void oops_error(short error, short code, short mode){ // mode is 0 for scened, 1 for game, 2 for pced + Str255 error_str1, error_str2; + static const char* progname[] = {"the scenario editor", "Blades of Exile", "the PC editor"}; + static const char* filetname[] = {"scenario", "game", "game"}; SysBeep(50); SysBeep(50); SysBeep(50); - sprintf((char *) error_str,"Giving the scenario editor more memory might also help. Be sure to back your scenario up often. Error number: %d.",error); + sprintf("The program encountered an error while loading/saving/creating the %s. To prevent future problems, the program will now terminate. Trying again may solve the problem.", filetname[mode]); + sprintf((char *) error_str2,"Giving %s more memory might also help. Be sure to back your %s up often. Error number: %d.",progname[mode],filetname[mode],error); if(code != 0) - sprintf((char*) error_str,"%s Result code: %i.",error_str,code); - give_error("The program encountered an error while loading/saving/creating the scenario. To prevent future problems, the program will now terminate. Trying again may solve the problem.",(char *) error_str,0); + sprintf((char*) error_str2,"%s Result code: %i.",error_str2,code); + give_error((char*) error_str1,(char *) error_str2,0); ExitToShell(); } diff --git a/osx/misc/dlgutil.h b/osx/misc/dlgutil.h index 5789c648..3133c2aa 100644 --- a/osx/misc/dlgutil.h +++ b/osx/misc/dlgutil.h @@ -9,7 +9,7 @@ #define FCD fancy_choice_dialog short cd_create_custom_dialog(WindowPtr parent, Str255 strs[6],short pic_num,short btns[3]); -void oops_error(short error,short code = 0); +void oops_error(short error,short code = 0, short mode = 0); void give_error(char *text1, char *text2,short parent_num); void display_strings(char *text1, char *text2,short str_label_1,short str_label_2,short str_label_1b, short str_label_2b, char *title,short sound_num,short graphic_num,short graphic_type,short parent_num); void display_strings(short a1,short a2, short b1, short b2, char *title,short sound_num,short graphic_num,short graphic_type,short parent_num); diff --git a/osx/misc/fileio.cpp b/osx/misc/fileio.cpp index 9c2faa6c..97c5848d 100644 --- a/osx/misc/fileio.cpp +++ b/osx/misc/fileio.cpp @@ -7,6 +7,7 @@ */ #include +#include #include //#include "scen.global.h" #include @@ -230,6 +231,63 @@ FSSpec nav_put_party() throw(no_file_chosen) { return file_to_save; } +struct header_posix_ustar { + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char checksum[8]; + char typeflag[1]; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; + char pad[12]; +}; + +#include + +header_posix_ustar generateTarHeader(const std::string& fileName, unsigned long long fileSize,bool directory=false){ + if(fileSize>077777777777LL) + throw length_error("Specified file size >= 8 GB"); + if(fileName.length()>=100) + throw length_error("Specified file name longer than 99 characters."); + header_posix_ustar header; + + sprintf(header.name,"%s",fileName.c_str()); + sprintf(header.mode,"%07o",0600); + //leave uid filled with NULs + //leave gid filled with NULs + sprintf(header.size,"%011o",fileSize); + sprintf(header.mtime,"%011o",time(NULL)); + memset(header.checksum,' ',8); + header.typeflag[0]=directory?'5':'0'; + //leave linkname filled with NULs + sprintf(header.magic,"ustar "); //overwrites header with " \0" + //leave uname filled with NULs + //leave gname filled with NULs + //leave devmajor filled with NULs + //leave devminor filled with NULs + //leave prefix filled with NULs + //leave pad filled with NULs + + unsigned int sum=0; + unsigned char* ptr=reinterpret_cast(&header); + for(unsigned int i=0; i0777777) + throw runtime_error("Checksum overflow"); + sprintf(header.checksum,"%o",sum); + return(header); +} + bool load_scenario(FSSpec file_to_load){ short i,file_id; bool file_ok = false; @@ -909,40 +967,33 @@ void load_spec_graphics() CloseResFile(custRef); } +bool load_party_v1(FSSpec file_to_load, bool town_restore, bool in_scen, bool maps_there, bool must_port); +bool load_party_v2(FSSpec file_to_load, bool town_restore, bool in_scen, bool maps_there); bool load_party(FSSpec file_to_load){ long file_size; OSErr error; - short file_id,i; bool town_restore = false; bool maps_there = false; bool in_scen = false; - bool new_format = false; + enum {old_mac, old_win, new_oboe, unknown} format; //char flag_data[8]; - - long len,store_len,count; - char *party_ptr; - char *pc_ptr; + long len; // flag_type flag; // flag_type *flag_ptr; - short flag; - legacy::party_record_type store_party; - legacy::setup_save_type store_setup; - legacy::pc_record_type store_pc[6]; - legacy::out_info_type store_out_info; - legacy::current_town_type store_c_town; - legacy::big_tr_type t_d; - legacy::town_item_list t_i; - legacy::stored_items_list_type stored_items[3]; - legacy::stored_town_maps_type town_maps; - legacy::stored_outdoor_maps_type o_maps; - unsigned char misc_i[64][64], sfx[64][64]; + short vers,file_id; + struct __attribute__((packed)) {ushort a; ushort b; ushort c; ushort d; ushort e;} flags; - static const short flags[3][2] = { + static const unsigned short mac_flags[3][2] = { {5790,1342}, // slot 0 ... 5790 - out, 1342 - town {100,200}, // slot 1 ... 100 - in scenario, 200 - not in {3422,5567} // slot 2 ... 3422 - no maps, 5567 - maps }; + static const unsigned short win_flags[3][2] = { + {40470,15877}, // slot 0 ... 40470 - out, 15877 - town + {25600,51200}, // slot 1 ... 25600 - in scenario, 51200 - not in + {24077,48917} // slot 2 ... 24077 - no maps, 48917 - maps + }; // but if the first flag is 0x0B0E, we have a new-format save // the three flags still follow that. error = FSpOpenDF(&file_to_load,1,&file_id); @@ -953,43 +1004,151 @@ bool load_party(FSSpec file_to_load){ } - file_size = sizeof(legacy::party_record_type); // 45368 + //file_size = sizeof(legacy::party_record_type); // 45368 - len = sizeof(short); // 2 + len = sizeof(flags); // 2 // sprintf((char *) debug, " Len %d ", (short) len); // add_string_to_buf((char *) debug); - for (i = 0; i < 3; i++) { - error = FSRead(file_id, &len, (char *) &flag); - if (error != 0) { - FSClose(file_id); - FCD(1064,0); - return false; + error = FSRead(file_id, &len, (char*) &flags); + if(error != 0) { + FSClose(file_id); + FCD(1063,0); + return false; + } + + if(mac_is_intel && flags.a == 0x0B0E){ // new format + format = new_oboe; + if(flags.b == mac_flags[0][1]) town_restore = true; + else if(flags.b != mac_flags[0][0]) format = unknown; + if(flags.c == mac_flags[1][0]) in_scen = true; + else if(flags.c != mac_flags[1][1]) format = unknown; + if(flags.d == mac_flags[2][1]) maps_there = true; + else if(flags.d != mac_flags[2][0]) format = unknown; + vers = flags.e; + }else if(!mac_is_intel && flags.a == 0x0E0B){ // new format + format = new_oboe; + flip_short((short*)&flags.b); + flip_short((short*)&flags.c); + flip_short((short*)&flags.d); + flip_short((short*)&flags.e); + if(flags.b == mac_flags[0][1]) town_restore = true; + else if(flags.b != mac_flags[0][0]) format = unknown; + if(flags.c == mac_flags[1][0]) in_scen = true; + else if(flags.c != mac_flags[1][1]) format = unknown; + if(flags.d == mac_flags[2][1]) maps_there = true; + else if(flags.d != mac_flags[2][0]) format = unknown; + vers = flags.e; + }else if(flags.a == mac_flags[0][0] || flags.a == mac_flags[0][1]){ // old format + if(mac_is_intel){ // it's actually a windows save + flip_short((short*)&flags.a); + flip_short((short*)&flags.b); + flip_short((short*)&flags.c); + if(flags.b == win_flags[0][1]) town_restore = true; + else if(flags.b != win_flags[0][0]) format = unknown; + if(flags.c == win_flags[1][0]) in_scen = true; + else if(flags.c != win_flags[1][1]) format = unknown; + if(flags.d == win_flags[2][1]) maps_there = true; + else if(flags.d != win_flags[2][0]) format = unknown; + }else{ // mac save + if(flags.b == mac_flags[0][1]) town_restore = true; + else if(flags.b != mac_flags[0][0]) format = unknown; + if(flags.c == mac_flags[1][0]) in_scen = true; + else if(flags.c != mac_flags[1][1]) format = unknown; + if(flags.d == mac_flags[2][1]) maps_there = true; + else if(flags.d != mac_flags[2][0]) format = unknown; } -// flag_ptr = (flag_type *) flag_data; -// flag = *flag_ptr; - if (flag == 0x0B0E) { // new format save - new_format = true; - i--; - continue; + }else if(flags.a == win_flags[0][0] || flags.a == win_flags[0][1]){ // old format + if(mac_is_intel){ // it's actually a macintosh save + flip_short((short*)&flags.a); + flip_short((short*)&flags.b); + flip_short((short*)&flags.c); + if(flags.b == mac_flags[0][1]) town_restore = true; + else if(flags.b != mac_flags[0][0]) format = unknown; + if(flags.c == mac_flags[1][0]) in_scen = true; + else if(flags.c != mac_flags[1][1]) format = unknown; + if(flags.d == mac_flags[2][1]) maps_there = true; + else if(flags.d != mac_flags[2][0]) format = unknown; + }else{ // mac save + if(flags.b == win_flags[0][1]) town_restore = true; + else if(flags.b != win_flags[0][0]) format = unknown; + if(flags.c == win_flags[1][0]) in_scen = true; + else if(flags.c != win_flags[1][1]) format = unknown; + if(flags.d == win_flags[2][1]) maps_there = true; + else if(flags.d != win_flags[2][0]) format = unknown; } - if(mac_is_intel && !new_format) flip_short(&flag); // because the old format save was made for non-intel macs - if ((flag != flags[i][0]) && (flag != flags[i][1])) { // OK Exile II save file? - FSClose(file_id); + }else format = unknown; + + FSClose(file_id); + switch(format){ + case old_mac: + return load_party_v1(file_to_load, town_restore, in_scen, maps_there, mac_is_intel); + case old_win: + return load_party_v1(file_to_load, town_restore, in_scen, maps_there, !mac_is_intel); + case new_oboe: + return load_party_v2(file_to_load, town_restore, in_scen, maps_there); + case unknown: FCD(1063,0); return false; - } - - if ((i == 0) && (flag == flags[i][1])) - town_restore = true; - if ((i == 1) && (flag == flags[i][0])) { - in_scen = true; - } - if ((i == 2) && (flag == flags[i][1])) - maps_there = true; } +// for (i = 0; i < 3; i++) { +// error = FSRead(file_id, &len, (char *) &flag); +// if (error != 0) { +// FSClose(file_id); +// FCD(1064,0); +// return false; +// } +//// flag_ptr = (flag_type *) flag_data; +//// flag = *flag_ptr; +// if (flag == 0x0B0E) { // new format save +// new_format = true; +// i--; +// continue; +// } +// if(mac_is_intel && !new_format) flip_short(&flag); // because the old format save was made for non-intel macs +// if ((flag != flags[i][0]) && (flag != flags[i][1])) { // OK Exile II save file? +// FSClose(file_id); +// FCD(1063,0); +// return false; +// } +// +// if ((i == 0) && (flag == flags[i][1])) +// town_restore = true; +// if ((i == 1) && (flag == flags[i][0])) { +// in_scen = true; +// } +// if ((i == 2) && (flag == flags[i][1])) +// maps_there = true; +// } + +} + +bool load_party_v1(FSSpec file_to_load, bool town_restore, bool in_scen, bool maps_there, bool must_port){ + short file_id,i; + OSErr error = FSpOpenDF(&file_to_load,1,&file_id); + if (error != 0) { + FCD(1064,0); + SysBeep(2); + return false; + } + + legacy::party_record_type store_party; + legacy::setup_save_type store_setup; + legacy::pc_record_type store_pc[6]; + legacy::out_info_type store_out_info; + legacy::current_town_type store_c_town; + legacy::big_tr_type t_d; + legacy::town_item_list t_i; + legacy::stored_items_list_type stored_items[3]; + legacy::stored_town_maps_type town_maps; + legacy::stored_outdoor_maps_type o_maps; + unsigned char misc_i[64][64], sfx[64][64]; + char *party_ptr; + char *pc_ptr; + long len,store_len,count; + // LOAD PARTY len = (long) sizeof(legacy::party_record_type); // 45368 store_len = len; @@ -999,7 +1158,7 @@ bool load_party(FSSpec file_to_load){ FCD(1064,0); return false; } - port_party(&store_party); + if(must_port) port_party(&store_party); party_ptr = (char*) &store_party; for (count = 0; count < store_len; count++) party_ptr[count] ^= 0x5C; @@ -1024,7 +1183,7 @@ bool load_party(FSSpec file_to_load){ FCD(1064,0); return false; } - port_pc(&store_pc[i]); + if(must_port) port_pc(&store_pc[i]); pc_ptr = (char*) &store_pc[i]; for (count = 0; count < store_len; count++) pc_ptr[count] ^= 0x6B; @@ -1052,7 +1211,7 @@ bool load_party(FSSpec file_to_load){ FCD(1064,0); return false; } - port_c_town(&store_c_town); + if(must_port) port_c_town(&store_c_town); len = (long) sizeof(legacy::big_tr_type); if ((error = FSRead(file_id, &len, (char *) &t_d)) != 0){ @@ -1061,7 +1220,7 @@ bool load_party(FSSpec file_to_load){ FCD(1064,0); return false; } - port_t_d(&t_d); + if(must_port) port_t_d(&t_d); len = (long) sizeof(legacy::town_item_list); if ((error = FSRead(file_id, &len, (char *) &t_i)) != 0){ @@ -1169,10 +1328,268 @@ bool load_party(FSSpec file_to_load){ return true; } -void save_party(FSSpec dest_file) +#include + +bool load_party_v2(FSSpec file_to_load, bool town_restore, bool in_scen, bool maps_there){ + FSRef dest_ref; + char* buf = new char[200]; + FSpMakeFSRef(&file_to_load, &dest_ref); + FSRefMakePath(&dest_ref, (UInt8*)&buf, 200); + FILE* f = fopen(buf,"rb"); + delete buf; + + // TODO: Write the parsers and stuff + /* Skip header */ + fseek(f, sizeof(short) * 5, SEEK_SET); + gzFile party_file = gzdopen(fileno(f), "rb"); + + /* Initialize various variables */ + header_posix_ustar header; + istringstream sin; + string tar_name; + string tar_entry; + size_t tar_size; + int x; + map party_archive; + + /* Split the tar archive into its component files */ + while(!gzeof(party_file)){ + gzread(party_file, &header, sizeof(header)); + sscanf(header.size, "%o", &tar_size); + tar_name = header.name; + buf = new char[tar_size]; + gzread(party_file, buf, tar_size); + tar_entry = buf; + delete buf; + party_archive[tar_name] = tar_entry; + gzseek(party_file, sizeof(header) * 2, SEEK_CUR); + } + + /* Read the data from each file */ + if(party_archive.find("save/party.txt") == party_archive.end()){ + FCD(1064,0); + return false; + }else{ + sin.str(party_archive["save/party.txt"]); + univ.party.readFrom(sin); + } + for(int i = 0; i < 6; i++){ + buf = new char[20]; + sprintf(buf,"save/pc%i.txt",i); + string f_name = buf; + delete buf; + if(party_archive.find(f_name) == party_archive.end()){ + FCD(1064,0); + return false; + }else{ + sin.str(party_archive[f_name]); + univ.party.adven[i].readFrom(sin); + } + } + if(in_scen){ + if(town_restore){ + if(party_archive.find("save/town.txt") == party_archive.end()){ + FCD(1064,0); + return false; + }else{ + sin.str(party_archive["save/town.txt"]); + univ.town.readFrom(sin); + } + if(party_archive.find("save/townmaps.dat") == party_archive.end()){ + FCD(1064,0); + return false; + }else{ + sin.str(party_archive["save/townmaps.dat"]); + for(int i = 0; i < 200; i++) + for(int j = 0; j < 8; j++) + for(int k = 0; k < 64; k++) + univ.town_maps[i][j][k] = sin.get(); + } + } + if(party_archive.find("save/out.txt") == party_archive.end()){ + FCD(1064,0); + return false; + }else{ + sin.str(party_archive["save/out.txt"]); + univ.out.readFrom(sin); + } + if(party_archive.find("save/outmaps.dat") == party_archive.end()){ + FCD(1064,0); + return false; + }else{ + sin.str(party_archive["save/outmaps.dat"]); + for(int i = 0; i < 100; i++) + for(int j = 0; j < 6; j++) + for(int k = 0; k < 48; k++) + univ.out_maps[i][j][k] = sin.get(); + } + } + return true; +} + +bool save_party(FSSpec dest_file) //mode; // 0 - normal 1 - save as { - printf("Saving is currently disabled.\n"); + //printf("Saving is currently disabled.\n"); + bool in_scen = !univ.party.scen_name[0]; + bool in_town = univ.town.num < 200; + bool save_maps = !univ.party.stuff_done[306][0]; + + /* Open the GZip file and write the (uncompressed) header */ + FSRef dest_ref; + char* path = new char[200]; + FSpMakeFSRef(&dest_file, &dest_ref); + FSRefMakePath(&dest_ref, (UInt8*)&path, 200); + //buf = new char[10000]; + FILE* f = fopen(path,"wb"); + short flags[] = { + 0x0B0E, // to indicate new format + in_town ? 1432 : 5790, // is the party in town? + in_scen ? 100 : 200, // is the party in a scenario? + save_maps ? 5567 : 3422, // is the save maps feature enabled? + 0x0100, // current version number, major and minor revisions only + // Version 1 indicates a beta format that won't be supported in the final release + }; + if(!mac_is_intel) // must flip all the flags to little-endian + for(int i = 0; i < 5; i++) + flip_short(&flags[i]); + fwrite((char*)flags, sizeof(short), 5, f); + gzFile party_file = gzdopen(fileno(f),"wb"); + delete path; + + /* Initialize buffer and other variables */ + header_posix_ustar header; + ostringstream sout; + string tar_entry; + size_t tar_size; + int x; + + /* Write main party data to a buffer, and then to the file */ + header = generateTarHeader("save/party.txt",tar_size); + sout.write((char*)&header, sizeof(header)); + univ.party.writeTo(sout); + //write the footer to end the file + for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++) + sout.put('\0'); + tar_entry = sout.str(); + tar_size = tar_entry.length(); + x = gzwrite(party_file, tar_entry.c_str(), tar_size); + if(x == 0) { // error + gzerror(party_file, &x); + oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1); + gzclose(party_file); + return false; + } + sout.str(""); // clear the stream (I think) + + /* Write player character data to a buffer, and then to the file */ + for(int i = 0; i < 6; i++){ + char f_name[20]; + sprintf(f_name,"save/pc%i.txt",i+1); + header = generateTarHeader(f_name,tar_size); + sout.write((char*)&header, sizeof(header)); + univ.party.adven[i].writeTo(sout); + //write the footer to end the file + for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++) + sout.put('\0'); + tar_entry = sout.str(); + tar_size = tar_entry.length(); + x = gzwrite(party_file, tar_entry.c_str(), tar_size); + if(x == 0) { // error + gzerror(party_file, &x); + oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1); + gzclose(party_file); + return false; + } + sout.str(""); // clear the stream (I think) + } + + if(in_scen){ + if(in_town){ + /* Write current town data to a buffer, and then to the file */ + header = generateTarHeader("save/town.txt",tar_size); + sout.write((char*)&header, sizeof(header)); + univ.town.writeTo(sout); + //write the footer to end the file + for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++) + sout.put('\0'); + tar_entry = sout.str(); + tar_size = tar_entry.length(); + x = gzwrite(party_file, tar_entry.c_str(), tar_size); + if(x == 0) { // error + gzerror(party_file, &x); + oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1); + gzclose(party_file); + return false; + } + sout.str(""); // clear the stream (I think) + + if(save_maps){ + /* Write town maps data to a buffer, and then to the file */ + header = generateTarHeader("save/townmaps.dat",tar_size); + sout.write((char*)&header, sizeof(header)); + for(int i = 0; i < 200; i++) + for(int j = 0; j < 8; j++) + for(int k = 0; k < 64; k++) + sout.put(univ.town_maps[i][j][k]); + //write the footer to end the file + for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++) + sout.put('\0'); + tar_entry = sout.str(); + tar_size = tar_entry.length(); + x = gzwrite(party_file, tar_entry.c_str(), tar_size); + if(x == 0) { // error + gzerror(party_file, &x); + oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1); + gzclose(party_file); + return false; + } + sout.str(""); // clear the stream (I think) + } + } + + /* Write current outdoors data to a buffer, and then to the file */ + header = generateTarHeader("save/out.txt",tar_size); + sout.write((char*)&header, sizeof(header)); + univ.out.writeTo(sout); + //write the footer to end the file + for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++) + sout.put('\0'); + tar_entry = sout.str(); + tar_size = tar_entry.length(); + x = gzwrite(party_file, tar_entry.c_str(), tar_size); + if(x == 0) { // error + gzerror(party_file, &x); + oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1); + gzclose(party_file); + return false; + } + sout.str(""); // clear the stream (I think) + + if(save_maps){ + /* Write outdoor maps data to a buffer, and then to the file */ + header = generateTarHeader("save/outmaps.dat",tar_size); + sout.write((char*)&header, sizeof(header)); + for(int i = 0; i < 100; i++) + for(int j = 0; j < 6; j++) + for(int k = 0; k < 48; k++) + sout.put(univ.out_maps[i][j][k]); + //write the footer to end the file + for(unsigned int j=0; j<2*sizeof(header_posix_ustar); j++) + sout.put('\0'); + tar_entry = sout.str(); + tar_size = tar_entry.length(); + x = gzwrite(party_file, tar_entry.c_str(), tar_size); + if(x == 0) { // error + gzerror(party_file, &x); + oops_error((x == Z_ERRNO) ? Z_ERRNO + 1000 : 1, (x == Z_ERRNO) ? errno : x, 1); + gzclose(party_file); + return false; + } + sout.str(""); // clear the stream (I think) + } + } + gzclose(party_file); // NavReplyRecord reply; // OSErr error; // short file_id; diff --git a/osx/misc/fileio.h b/osx/misc/fileio.h index 3e646ece..324191c0 100644 --- a/osx/misc/fileio.h +++ b/osx/misc/fileio.h @@ -27,4 +27,4 @@ void load_spec_graphics(); FSSpec nav_get_party() throw(no_file_chosen); FSSpec nav_put_party() throw(no_file_chosen); bool load_party(FSSpec file_to_load); -void save_party(FSSpec dest_file); +bool save_party(FSSpec dest_file); diff --git a/osx/monster.h b/osx/monster.h index 268629ec..72994ad1 100644 --- a/osx/monster.h +++ b/osx/monster.h @@ -118,4 +118,5 @@ public: short picture_num; cMonster& operator = (legacy::monster_record_type& old); + void writeTo(ostream& file, string prefix); }; diff --git a/osx/outdoors.cpp b/osx/outdoors.cpp index 622134a9..174f0d19 100644 --- a/osx/outdoors.cpp +++ b/osx/outdoors.cpp @@ -132,3 +132,46 @@ cOutdoors::cCreature& cOutdoors::cCreature::operator = (legacy::outdoor_creature m_loc.y = old.m_loc.y; return *this; } + +void cOutdoors::writeTo(ostream& file){ +// for(int i = 0; i < 48; i++){ +// file << expl[i][0]; +// for(int j = 1; j < 48; j++){ +// file << '\t' << expl[i][j]; +// } +// file << endl; +// } +} + +void cOutdoors::cWandering::writeTo(ostream& file, string prefix){ + for(int i = 0; i < 7; i++) + file << prefix << "HOSTILE " << i << ' ' << monst[i] << endl; + for(int i = 0; i < 3; i++) + file << prefix << "FRIEND " << i << ' ' << friendly[i] << endl; + file << prefix << "MEET " << spec_on_meet << endl; + file << prefix << "WIN " << spec_on_win << endl; + file << prefix << "FLEE " << spec_on_flee << endl; + file << prefix << "FLAGS " << cant_flee << endl; + file << prefix << "SDF " << end_spec1 << ' ' << end_spec2 << endl; +} + +void cOutdoors::cWandering::readAttrFrom(string cur, istream& sin){ + if(cur == "HOSTILE"){ + int i; + sin >> i; + sin >> monst[i]; + }else if(cur == "FRIEND"){ + int i; + sin >> i; + sin >> friendly[i]; + }else if(cur == "MEET") + sin >> spec_on_meet; + else if(cur == "WIN") + sin >> spec_on_win; + else if(cur == "FLEE") + sin >> spec_on_flee; + else if(cur == "FLAGS") + sin >> cant_flee; + else if(cur == "SDF") + sin >> end_spec1 >> end_spec2; +} diff --git a/osx/outdoors.h b/osx/outdoors.h index 51a6d71d..031470a5 100644 --- a/osx/outdoors.h +++ b/osx/outdoors.h @@ -24,6 +24,8 @@ public: short end_spec1,end_spec2; cWandering& operator = (legacy::out_wandering_type old); + void writeTo(ostream& file, string prefix = ""); + void readAttrFrom(string cur, istream& sin); }; class cCreature { // formerly outdoor_creature_type public: @@ -55,4 +57,5 @@ public: cOutdoors(); cOutdoors& operator = (legacy::outdoor_record_type& old); + void writeTo(ostream& file); }; diff --git a/osx/party.cpp b/osx/party.cpp index e28093bf..1cfd4fd7 100644 --- a/osx/party.cpp +++ b/osx/party.cpp @@ -170,6 +170,7 @@ bool cParty::add_to_journal(short event, short day){ cJournal entry; entry.str_num = event; entry.day = day; + // TODO: locate the strings and store them in the record. journal.push_back(entry); return true; } @@ -179,6 +180,7 @@ bool cParty::record(short what, short where){ cEncNote note; note.str_num = what; note.where = where; + // TODO: locate the strings and store them in the record. special_notes.push_back(note); return true; } @@ -191,3 +193,259 @@ bool cParty::start_timer(short time, short node, short type){ t.node_to_call = node; party_event_timers.push_back(t); } + +void cParty::writeTo(ostream& file){ + file << "AGE " << age << endl; + file << "GOLD " << gold << endl; + file << "FOOD " << food << endl; + for(int i = 0; i < 310; i++) + for(int j = 0; j < 50; j++) + if(stuff_done[i][j] > 0) + file << "SDF " << i << ' ' << j << ' ' << stuff_done[i][j] << endl; + for(int i = 0; i < 200; i++) + if(item_taken[i][0] > 0 || item_taken[i][1] > 0 || item_taken[i][2] > 0 || item_taken[i][3] > 0 || + item_taken[i][4] > 0 || item_taken[i][5] > 0 || item_taken[i][6] > 0 || item_taken[i][7] > 0) + file << "ITEMTAKEN " << i << ' ' << item_taken[i][0] << ' ' << item_taken[i][1] << ' ' + << item_taken[i][2] << ' ' << item_taken[i][3] << ' ' << item_taken[i][4] << ' ' << item_taken[i][5] + << ' ' << item_taken[i][6] << ' ' << item_taken[i][7] << endl; + file << "LIGHT " << light_level << endl; + file << "OUTCORNER " << outdoor_corner.x << ' ' << outdoor_corner.y << endl; + file << "INWHICHCORNER " << i_w_c.x << ' ' << i_w_c.y << endl; + file << "SECTOR " << p_loc.x << ' ' << p_loc.y << endl; + file << "LOCINSECTOR " << loc_in_sec.x << ' ' << loc_in_sec.y << endl; + // TODO: Delegate this to the cVehicle class + for(int i = 0; i < 30; i++){ + if(!boats[i].exists) continue; + file << "BOAT " << i << ' '; + file << boats[i].loc.x << ' ' << boats[i].loc.y << ' '; + file << boats[i].loc_in_sec.x << ' ' << boats[i].loc_in_sec.y << ' '; + file << boats[i].sector.x << ' ' << boats[i].sector.y << ' '; + file << boats[i].which_town << ' ' << (short)boats[i].property << endl; + } + for(int i = 0; i < 30; i++){ + if(!horses[i].exists) continue; + file << "HORSE " << i << ' '; + file << horses[i].loc.x << ' ' << horses[i].loc.y << ' '; + file << horses[i].loc_in_sec.x << ' ' << horses[i].loc_in_sec.y << ' '; + file << horses[i].sector.x << ' ' << horses[i].sector.y << ' '; + file << horses[i].which_town << ' ' << (short)horses[i].property << endl; + } + file << "IN " << in_boat << ' ' << in_horse << endl; + for(int i = 0; i < 5; i++) + for(int j = 0; j < 50; j++) + if(magic_store_items[i][j].variety > ITEM_TYPE_NO_ITEM){ + ostringstream sout; + sout << "MAGICSTORE " << i << ' ' << j << ' '; + magic_store_items[i][j].writeTo(file, sout.str()); + } + for(int i = 0; i < 256; i++) + if(m_seen[i]) + file << "ROSTER " << i << endl; + for(int i = 0; i < 10; i++) + if(out_c[i].exists){ + file << "ENCOUNTER " << i << " DIRECTION " << out_c[i].direction << endl; + file << "ENCOUNTER " << i << " SECTOR " << out_c[i].which_sector.x << ' ' << out_c[i].which_sector.y << endl; + file << "ENCOUNTER " << i << " LOCINSECTOR " << out_c[i].m_loc.x << ' ' << out_c[i].m_loc.y << endl; + file << "ENCOUNTER " << i << " HOME " << out_c[i].home_sector.x << ' ' << out_c[i].home_sector.y << endl; + ostringstream sout; + sout << "ENCOUNTER " << i << ' '; + out_c[i].what_monst.writeTo(file,sout.str()); + } + for(int i = 0; i < 4; i++) + if(imprisoned_monst[i] > 0) + file << "SOULCRYSTAL " << i << ' ' << imprisoned_monst[i] << endl; + file << "DIRECTION " << direction << endl; + file << "WHICHSLOT " << at_which_save_slot << endl; + for(int i = 0; i < 20; i++) + if(alchemy[i]) + file << "ALCHEMY " << i << endl; + for(int i = 0; i < 200; i++) + if(can_find_town[i]) + file << "TOWN " << i << endl; + for(int i = 0; i < 100; i++) + if(key_times[i]) + file << "EVENT " << i << ' ' << key_times[i] << endl; + for(int i = 0; i < 50; i++) + if(spec_items[i]) + file << "ITEM " << i << endl; + for(int i = 0; i < 120; i++) + if(help_received[i]) + file << "HELP " << i << endl; + for(int i = 0; i < 200; i++) + if(m_killed[i] > 0) + file << "TOWNSLAUGHTER " << i << ' ' << m_killed[i] << endl; + file << "KILLS " << total_m_killed << endl; + file << "DAMAGE " << total_dam_done << endl; + file << "WOUNDS " << total_dam_taken << endl; + file << "EXPERIENCE " << total_xp_gained << endl; + file << "SCENARIO " << scen_name << endl; + file << "WON " << scen_won << endl; + file << "PLAYED " << scen_played << endl; + for(campIter iter = campaign_flags.begin(); iter != campaign_flags.end(); iter++){ + for(int i = 0; i < iter->second.size(); i++) + if(iter->second[i] > 0) + file << "CAMPAIGN \"" << iter->first << "\" " << i << ' ' << iter->second[i] << endl; + } + for(int i = 0; i < 250; i++) + if(graphicUsed[i]) + file << "GRAPHIC " << i << endl; + for(int i = 0; i < party_event_timers.size(); i++) + file << "TIMER " << i << ' ' << party_event_timers[i].time << ' ' << party_event_timers[i].global_or_town + << ' ' << party_event_timers[i].node_to_call << endl; + file << '\f'; + for(int i = 0; i < 4; i++){ + for(int j = 0; j < 64; j++){ + file << setup[i][j][0]; + for(int k = 1; k < 64; k++) + file << '\t' << setup[i][j][k]; + file << endl; + } + file << '\f'; + } + // TODO: The three journal note variables + // TODO: creature_save + // TODO: stored_items + // TODO: summons +} + +void cParty::readFrom(istream& file){ + // TODO: Error-check input + istringstream bin, sin; + string cur; + getline(file, cur, '\f'); + bin.str(cur); + while(bin) { // continue as long as no error, such as eof, occurs + getline(bin, cur); + sin.str(cur); + sin >> cur; + if(cur == "AGE") + sin >> age; + else if(cur == "GOLD") + sin >> gold; + else if(cur == "FOOD") + sin >> food; + else if(cur == "SDF"){ + int i,j; + sin >> i >> j; + sin >> stuff_done[i][j]; + }else if(cur == "ITEMTAKEN"){ + int i; + sin >> i; + sin >> item_taken[i][0] >> item_taken[i][1] >> item_taken[i][2] >> item_taken[i][3] + >> item_taken[i][4] >> item_taken[i][5] >> item_taken[i][6] >> item_taken[i][7]; + }else if(cur == "LIGHT") + sin >> light_level; + else if(cur == "OUTCORNER") + sin >> outdoor_corner.x >> outdoor_corner.y; + else if(cur == "INWHICHCORNER") + sin >> i_w_c.x >> i_w_c.y; + else if(cur == "SECTOR") + sin >> p_loc.x >> p_loc.y; + else if(cur == "LOCINSECTOR") + sin >> loc_in_sec.x >> loc_in_sec.y; + else if(cur == "BOAT"){ + int i; + sin >> i; + sin >> boats[i].loc.x >> boats[i].loc.y >> boats[i].loc_in_sec.x >> boats[i].loc_in_sec.y + >> boats[i].sector.x >> boats[i].sector.y >> boats[i].which_town >> boats[i].property; + boats[i].exists = true; + }else if(cur == "HORSE"){ + int i; + sin >> i; + sin >> horses[i].loc.x >> horses[i].loc.y >> horses[i].loc_in_sec.x >> horses[i].loc_in_sec.y + >> horses[i].sector.x >> horses[i].sector.y >> horses[i].which_town >> horses[i].property; + horses[i].exists = true; + }else if(cur == "IN") + sin >> in_boat >> in_horse; + else if(cur == "MAGICSTORE"){ + int i,j; + sin >> i >> j >> cur; + magic_store_items[i][j].readAttrFrom(cur,sin); + }else if(cur == "ROSTER"){ + int i; + sin >> i; + m_seen[i] = true; + }else if(cur == "ENCOUNTER"){ + int i; + sin >> i >> cur; + if(cur == "DIRECTION") + sin >> out_c[i].direction; + else if(cur == "SECTOR") + sin >> out_c[i].which_sector.x >> out_c[i].which_sector.y; + else if(cur == "LOCINSECTOR") + sin >> out_c[i].m_loc.x >> out_c[i].m_loc.y; + else if(cur == "HOME") + sin >> out_c[i].home_sector.x >> out_c[i].home_sector.y; + else out_c[i].what_monst.readAttrFrom(cur,sin); + }else if(cur == "SOULCRYSTAL"){ + int i; + sin >> i; + sin >> imprisoned_monst[i]; + }else if(cur == "DIRECTION") + sin >> direction; + else if(cur == "WHICHSLOT") + sin >> at_which_save_slot; + else if(cur == "ALCHEMY"){ + int i; + sin >> i; + alchemy[i] = true; + }else if(cur == "TOWN"){ + int i; + sin >> i; + can_find_town[i] = true; + }else if(cur == "EVENT"){ + int i; + sin >> i; + sin >> key_times[i]; + }else if(cur == "ITEM"){ + int i; + sin >> i; + spec_items[i] = true; + }else if(cur == "HELP"){ + int i; + sin >> i; + help_received[i] = true; + }else if(cur == "TOWNSLAUGHTER"){ + int i; + sin >> i; + sin >> m_killed[i]; + }else if(cur == "KILLS") + sin >> total_m_killed; + else if(cur == "DAMAGE") + sin >> total_dam_done; + else if(cur == "WOUNDS") + sin >> total_dam_taken; + else if(cur == "EXPERIENCE") + sin >> total_xp_gained; + else if(cur == "SCENARIO") + sin >> scen_name; + else if(cur == "WON") + sin >> scen_won; + else if(cur == "PLAYED") + sin >> scen_played; + else if(cur == "CAMPAIGN"){ + int i,j; + if(sin.peek() == '"'){ + sin.get(); + getline(sin, cur, '"'); + }else sin >> cur; + sin >> i >> j; + while(campaign_flags[cur].size() < i) campaign_flags[cur].push_back(0); + campaign_flags[cur][i] = j; + }else if(cur == "GRAPHIC"){ + int i; + sin >> i; + graphicUsed[i] = true; + }else if(cur == "TIMER"){ + int i; + sin >> i; + sin >> party_event_timers[i].time >> party_event_timers[i].global_or_town >> party_event_timers[i].node_to_call; + } + } + getline(file, cur, '\f'); + bin.str(cur); + for(int i = 0; i < 4; i++) + for(int j = 0; j < 64; j++) + for(int k = 0; k < 64; k++) + bin >> setup[i][j][k]; +} \ No newline at end of file diff --git a/osx/party.h b/osx/party.h index 0d919921..a7c48d55 100644 --- a/osx/party.h +++ b/osx/party.h @@ -8,6 +8,7 @@ #include #include +#include using namespace std; namespace legacy { @@ -90,10 +91,11 @@ public: unsigned short setup[4][64][64]; // formerly setup_save_type cItemRec stored_items[3][115]; // formerly stored_items_list_type - string graphicsFile; // the name of the png file holding this party's custom item, pc, and summonable monster graphics + //string graphicsFile; // the name of the png file holding this party's custom item, pc, and summonable monster graphics cMonster summons; // an array of monsters which can be summoned by the parties items yet don't originate from this scenario bool graphicUsed[250]; // whether each custom graphics slot on the party's sheet is actually used; needed to place new custom graphics on the sheet. unsigned short scen_won, scen_played; // numbers of scenarios won and played respectively by this party + map > campaign_flags; cParty& operator = (legacy::party_record_type& old); void append(legacy::big_tr_type& old); @@ -113,4 +115,7 @@ public: typedef vector::iterator journalIter; typedef vector::iterator talkIter; typedef vector::iterator timerIter; + typedef map >::iterator campIter; + void writeTo(ostream& file); + void readFrom(istream& file); }; diff --git a/osx/pc.cpp b/osx/pc.cpp index f1e46c0a..8978edc3 100644 --- a/osx/pc.cpp +++ b/osx/pc.cpp @@ -25,7 +25,7 @@ cPlayer& cPlayer::operator = (legacy::pc_record_type old){ level = old.level; for(i = 0; i < 15; i++){ status[i] = old.status[i]; - advan[i] = old.advan[i]; + //advan[i] = old.advan[i]; traits[i] = old.traits[i]; } for(i = 0; i < 24; i++){ @@ -39,7 +39,7 @@ cPlayer& cPlayer::operator = (legacy::pc_record_type old){ which_graphic = old.which_graphic; weap_poisoned = old.weap_poisoned; race = old.race; - exp_adj = old.exp_adj; + //exp_adj = old.exp_adj; direction = old.direction; return *this; } @@ -88,11 +88,11 @@ cPlayer::cPlayer(){ weap_poisoned = 24; for (i = 0; i < 15; i++) { - advan[i] = false; + //advan[i] = false; traits[i] = false; } race = 0; - exp_adj = 100; + //exp_adj = 100; direction = 0; } @@ -145,12 +145,12 @@ cPlayer::cPlayer(long key,short slot){ weap_poisoned = 24; // was 16, as an E2 relic for (i = 0; i < 15; i++) { - advan[i] = false; + //advan[i] = false; traits[i] = false; } race = 0; - exp_adj = 100; + //exp_adj = 100; direction = 0; }else if(key == 'dflt'){ static const short pc_stats[6][19] = { @@ -219,11 +219,11 @@ cPlayer::cPlayer(long key,short slot){ } for (i = 0; i < 15; i++) { traits[i] = pc_t[slot][i]; - advan[i] = false; + //advan[i] = false; } race = pc_race[slot]; - exp_adj = 100; + //exp_adj = 100; direction = 0; which_graphic = pc_graphics[slot]; @@ -240,3 +240,116 @@ void operator -= (eMainStatus& stat, eMainStatus othr){ stat = (eMainStatus) (-10 + stat); } +void cPlayer::writeTo(ostream& file){ + file << "STATUS -1 " << main_status << endl; + file << "NAME " << name << endl; + file << "SKILL -2 " << max_health << endl; + file << "SKILL -1 " << max_sp << endl; + for(int i = 0; i < 30; i++) + if(skills[i] > 0) + file << "SKILL " << i << ' ' << skills[i] << endl; + file << "HEALTH " << cur_health << endl; + file << "MANA " << cur_sp << endl; + file << "EXPERIENCE " << experience << endl; + file << "SKILLPTS " << skill_pts << endl; + file << "LEVEL " << level << endl; + for(int i = 0; i < 15; i++) + if(status[i] != 0) + file << "STATUS " << i << ' ' << status[i] << endl; + for(int i; i < 24; i++) + if(items[i].variety > ITEM_TYPE_NO_ITEM){ + ostringstream sout; + sout << "ITEM " << i << ' '; + items[i].writeTo(file, sout.str()); + } + for(int i = 0; i < 24; i++) + if(equip[i]) + file << "EQUIP " << i << endl; + for(int i = 0; i < 62; i++) + if(mage_spells[i]) + file << "MAGE " << i << endl; + for(int i = 0; i < 62; i++) + if(priest_spells[i]) + file << "PRIEST " << i << endl; + for(int i = 0; i < 62; i++) + if(traits[i]) + file << "TRAIT " << i << endl; + file << "ICON " << which_graphic << endl; + file << "RACE " << race << endl; + file << "DIRECTION " << direction << endl; + file << "POISON " << weap_poisoned << endl; +} + +void cPlayer::readFrom(istream& file){ + istringstream bin, sin; + string cur; + getline(file, cur, '\f'); + bin.str(cur); + while(bin) { // continue as long as no error, such as eof, occurs + getline(bin, cur); + sin.str(cur); + sin >> cur; + if(cur == "STATUS"){ + int i; + sin >> i; + if(i < 0) sin >> main_status; + else sin >> status[i]; + }else if(cur == "NAME") + sin >> name; + else if(cur == "SKILL"){ + int i; + sin >> i; + switch(i){ + case -1: + sin >> max_sp; + break; + case -2: + sin >> max_health; + break; + default: + sin >> skills[i]; + } + }else if(cur == "HEALTH") + sin >> cur_health; + else if(cur == "MANA") + sin >> cur_sp; + else if(cur = "EXPERIENCE") + sin >> experience; + else if(cur == "SKILLPTS") + sin >> skill_pts; + else if(cur == "LEVEL") + sin >> level; + else if(cur == "STATUS"){ + int i; + sin >> i; + sin >> status[i]; + }else if(cur == "ITEM"){ + int i; + sin >> i >> cur; + items[i].readAttrFrom(cur, sin); + }else if(cur == "EQUIP"){ + int i; + sin >> i; + equip[i] = true; + }else if(cur == "MAGE"){ + int i; + sin >> i; + mage_spells[i] = true; + }else if(cur == "PRIEST"){ + int i; + sin >> i; + priest_spells[i] = true; + }else if(cur == "TRAIT"){ + int i; + sin >> i; + traits[i] = true; + }else if(cur == "ICON") + sin >> which_graphic; + else if(cur == "DIRECTION") + sin >> direction; + else if(cur == "RACE") + sin >> race; + else if(cur == "POISON") + sin >> weap_poisoned; + } +} diff --git a/osx/pc.h b/osx/pc.h index 1a700364..7c7e2b38 100644 --- a/osx/pc.h +++ b/osx/pc.h @@ -49,16 +49,18 @@ public: bool mage_spells[62]; short which_graphic; short weap_poisoned; - bool advan[15]; + //bool advan[15]; bool traits[15]; short race; - short exp_adj; + //short exp_adj; short direction; cPlayer& operator = (legacy::pc_record_type old); cPlayer(); cPlayer(long key,short slot); short get_tnl(); + void writeTo(ostream& file); + void readFrom(istream& file); }; void operator += (eMainStatus& stat, eMainStatus othr); diff --git a/osx/regtown.h b/osx/regtown.h index 4b5e1a38..6de09a91 100644 --- a/osx/regtown.h +++ b/osx/regtown.h @@ -28,6 +28,7 @@ public: short max_monst(); cBigTown(); + void writeTo(ostream& file); }; class cMedTown : public cTown { // formerly ave_tr_type @@ -46,6 +47,7 @@ public: short max_monst(); cMedTown(); + void writeTo(ostream& file); }; class cTinyTown : public cTown { // formerly tiny_tr_type @@ -64,4 +66,5 @@ public: short max_monst(); cTinyTown(); + void writeTo(ostream& file); }; diff --git a/osx/scenario.cpp b/osx/scenario.cpp index 7d238c02..d754e6f2 100644 --- a/osx/scenario.cpp +++ b/osx/scenario.cpp @@ -104,7 +104,7 @@ void cScenario::append(legacy::scen_item_data_type& old){ for(i = 0; i < 256; i++) strcpy((char*)scen_monsters[i].m_name,(char*)old.monst_names[i]); for(i = 0; i < 256; i++) - strcpy(ter_names[i],old.ter_names[i]); + ter_types[i].name = old.ter_names[i]; } __attribute__((deprecated)) diff --git a/osx/scenario.h b/osx/scenario.h index 60b301ac..d5894aa5 100644 --- a/osx/scenario.h +++ b/osx/scenario.h @@ -70,7 +70,7 @@ public: // scen_item_data_type scen_item_list { cItemRec scen_items[400]; //char monst_names[256][20]; - char ter_names[256][30]; + //char ter_names[256][30]; // }; //char scen_strs[270][256]; char scen_name[256]; @@ -87,5 +87,5 @@ public: char(& scen_strs(short i))[256]; cScenario& operator = (legacy::scenario_data_type& old); void append(legacy::scen_item_data_type& old); - void writeTo(short file_id); + void writeTo(ostream& file); }; diff --git a/osx/special.h b/osx/special.h index 46891bbe..e2e2ac0f 100644 --- a/osx/special.h +++ b/osx/special.h @@ -24,4 +24,5 @@ public: cSpecial(); cSpecial& operator = (legacy::special_node_type& old); + void writeTo(ostream& file); }; diff --git a/osx/talking.h b/osx/talking.h index 531217f0..d3e0747b 100644 --- a/osx/talking.h +++ b/osx/talking.h @@ -24,4 +24,5 @@ public: cNode talk_nodes[60]; cSpeech& operator = (legacy::talking_record_type& old); + void writeTo(ostream& file); }; diff --git a/osx/terrain.h b/osx/terrain.h index 86e90d91..163cee75 100644 --- a/osx/terrain.h +++ b/osx/terrain.h @@ -33,12 +33,13 @@ enum eTerSpec { TER_SPEC_CONVEYOR_WEST = 19, TER_SPEC_BLOCKED_TO_MONSTERS = 20, TER_SPEC_TOWN_ENTRANCE = 21, - TER_SPEC_CHNAGE_WHEN_USED = 22, + TER_SPEC_CHANGE_WHEN_USED = 22, TER_SPEC_CALL_SPECIAL_WHEN_USED = 23, }; class cTerrain { public: + string name; short picture; unsigned char blockage; unsigned char flag1; @@ -59,4 +60,5 @@ public: location obj_pos; // editor use only cTerrain& operator = (legacy::terrain_type_type& old); + void writeTo(ostream& file); }; diff --git a/osx/tmpltown.h b/osx/tmpltown.h index cb4a0ac2..2abe9cc8 100644 --- a/osx/tmpltown.h +++ b/osx/tmpltown.h @@ -24,6 +24,7 @@ public: }; cCityBlock blocks[15]; cTerRect ter_rects[10]; + void writeTo(ostream& file); }; class cBigTemplTown : public cBigTown, cTemplTown { @@ -39,6 +40,7 @@ public: unsigned char& lighting(size_t i, size_t r); short max_dim(); short max_monst(); + void writeTo(ostream& file); }; class cMedTemplTown : public cMedTown, cTemplTown { @@ -54,6 +56,7 @@ public: unsigned char& lighting(size_t i, size_t r); short max_dim(); short max_monst(); + void writeTo(ostream& file); }; class cTinyTemplTown : public cTinyTown, cTemplTown { diff --git a/osx/town.h b/osx/town.h index e1265dcb..1207f1e8 100644 --- a/osx/town.h +++ b/osx/town.h @@ -99,4 +99,5 @@ public: cTown(); cTown(short size); cTown& operator = (legacy::town_record_type& old); + void writeTo(ostream& file); }; diff --git a/osx/universe.cpp b/osx/universe.cpp index 820ba700..b35cf721 100644 --- a/osx/universe.cpp +++ b/osx/universe.cpp @@ -605,3 +605,128 @@ unsigned char cCurTown::sfx(char x, char y) const{ unsigned short(& cCurOut::operator [] (size_t i))[96]{ return out[i]; } + +void cCurOut::writeTo(ostream& file){ +// for(int i = 0; i < 96; i++){ +// file << expl[i][0]; +// for(int j = 1; j < 96; j++){ +// file << '\t' << expl[i][j]; +// } +// file << endl; +// } +// file << '\f'; +// for(int i = 9; i < 96; i++){ +// file << out[i][0]; +// for(int j = 1; j < 96; j++){ +// file << '\t' << out[i][j]; +// } +// file << endl; +// } +// file << '\f'; + for(int i = 0; i < 96; i++){ + file << out_e[i][0]; + for(int j = 1; j < 96; j++){ + file << '\t' << out_e[i][j]; + } + file << endl; + } +// file << "OUTDOORS 0 0" << endl; +// outdoors[0][0].writeTo(file); +// file << "OUTDOORS 0 1" << endl; +// outdoors[0][1].writeTo(file); +// file << "OUTDOORS 1 0" << endl; +// outdoors[1][0].writeTo(file); +// file << "OUTDOORS 1 1" << endl; +// outdoors[1][1].writeTo(file); +// file << endl; +} + +void cCurTown::writeTo(ostream& file){ + file << "TOWN " << num << endl; + file << "DIFFICULTY " << difficulty << endl; + if(hostile) file << "HOSTILE" << endl; + file << "INBOAT " << in_boat << endl; + file << "AT " << p_loc.x << ' ' << p_loc.y << endl; + for(int i; i < 115; i++) + if(items[i].variety > ITEM_TYPE_NO_ITEM){ + ostringstream sout; + sout << "ITEM " << i << ' '; + items[i].writeTo(file, sout.str()); + } + file << '\f'; + for(int i = 0; i < 64; i++){ + file << fields[i][0]; + for(int j = 1; j < 64; j++) + file << '\t' << fields[i][j]; + file << endl; + } + file << '\f' << record->max_dim() << endl; + for(int i = 0; i < record->max_dim(); i++){ + file << record->terrain(i,0); + for(int j = 1; j < record->max_dim(); j++) + file << '\t' << record->terrain(i,j); + file << endl; + } + file << '\f'; + // TODO: Write population +} + +void cCurTown::readFrom(istream& file){ + istringstream bin, sin; + string cur; + getline(file, cur, '\f'); + bin.str(cur); + while(bin){ + getline(bin, cur); + sin.str(cur); + sin >> cur; + if(cur == "TOWN") + sin >> num; + else if(cur == "DIFFICULTY") + sin >> difficulty; + else if(cur == "HOSTILE") + hostile = true; + else if(cur == "INBOAT") + sin >> in_boat; + else if(cur == "AT") + sin >> p_loc.x >> p_loc.y; + else if(cur == "ITEM"){ + int i; + sin >> i >> cur; + items[i].readAttrFrom(cur, sin); + } + } + getline(file, cur, '\f'); + bin.str(cur); + for(int i = 0; i < 64; i++) + for(int j = 1; j < 64; j++) + bin >> fields[i][j]; + getline(file, cur, '\f'); + bin.str(cur); + int dim; + bin >> dim; + if(record != NULL) delete record; + switch(dim){ + case 32: + record = new cTinyTown; + break; + case 48; + record = new cMedTown; + break; + case 64: + record = new cBigTown; + break; + } + for(int i = 0; i < dim; i++) + for(int j = 1; j < dim; j++) + bin >> record->terrain(i,j); + // TODO: Read population +} + + +void cCurOut::readFrom(istream& file){ + for(int i = 0; i < 96; i++) + for(int j = 1; j < 96; j++) + file >> out_e[i][j]; +} + diff --git a/osx/universe.h b/osx/universe.h index f2045fb2..26145890 100644 --- a/osx/universe.h +++ b/osx/universe.h @@ -31,7 +31,7 @@ public: cItemRec items[115]; // formerly town_item_list type - unsigned short template_terrain[64][64]; + //unsigned short template_terrain[64][64]; unsigned long fields[64][64]; void append(legacy::current_town_type& old,short which_size); @@ -95,6 +95,8 @@ public: bool set_ash(char x, char y, bool b); bool set_bones(char x, char y, bool b); bool set_rubble(char x, char y, bool b); + void writeTo(ostream& file); + void readFrom(istream& file); }; class cCurOut { @@ -110,6 +112,8 @@ public: void append(legacy::out_info_type& old); unsigned short(& operator [] (size_t i))[96]; + void writeTo(ostream& file); + void readFrom(istream& file); }; class cUniverse{ diff --git a/osx/vehicle.h b/osx/vehicle.h index d6a0f59c..ef2b5698 100644 --- a/osx/vehicle.h +++ b/osx/vehicle.h @@ -27,6 +27,7 @@ public: cVehicle(); cVehicle& operator = (legacy::horse_record_type& old); cVehicle& operator = (legacy::boat_record_type& old); + void writeTo(ostream& file); }; /*