home *** CD-ROM | disk | FTP | other *** search
/ WarCraft 2000 - Nuclear Epidemic / W2000.nrg / SOURCE.War2000 / LoadSave.cpp < prev    next >
C/C++ Source or Header  |  1998-09-29  |  26KB  |  991 lines

  1. #include "ddini.h"
  2. #include "ResFile.h"
  3. #include "FastDraw.h"
  4. #include "mgraph.h"
  5. #include "mouse.h"
  6. #include "menu.h"
  7. #include "MapDiscr.h"
  8. #include "multipl.h"
  9. #include "fog.h"
  10. #include "walls.h"
  11. #include "Nature.h"
  12. #include <time.h>
  13. #include "Nucl.h"
  14. #include "TopZones.h"
  15. #include "Megapolis.h"
  16. #include "FlyObj.h"
  17. #include <assert.h>
  18. #include "MapEdit.h"
  19. #include "3DSurf.h"
  20. #include "Strange.h"
  21. extern word NucList[128];
  22. extern word NucSN[128];
  23. extern bool NDone[128];
  24. extern word NNuc;
  25. char GameName[128];
  26. extern City CITY[8];
  27. extern bool EUsage[8192];
  28. extern AnmObject* GAnm[8192];
  29. void LoadNation(char* fn,byte msk,byte NIndex);
  30. extern word FlyMops[256][256];
  31. extern byte Locking[1024];//╚φ⌠. ε ßδεΩΦ≡εΓαφΦΦ ∩εΓσ≡⌡φε±≥Φ
  32. extern int RealLx;
  33. extern int RealLy;
  34. extern int Pitch;
  35. extern bool MiniMade;
  36. void SetSumms();
  37. void SAVMES(ResFile ff1,char* mes){
  38.     char mss[16];
  39.     memset(mss,0,16);
  40.     int len=strlen(mes);
  41.     if(len>10)len=16;
  42.     memcpy(mss,mes,len);
  43.     RBlockWrite(ff1,mss,16);
  44. };
  45. void SAVMES1(ResFile ff1,char* mes,int parm){
  46.     char mss[16];
  47.     char xxx[28];
  48.     sprintf(xxx,"%s %d",mes,parm);
  49.     memset(mss,0,16);
  50.     int len=strlen(xxx);
  51.     if(len>16)len=16;
  52.     memcpy(mss,xxx,len);
  53.     RBlockWrite(ff1,mss,16);
  54. };
  55. void LOADMES(ResFile ff1){
  56.     char zzz[16];
  57.     RBlockRead(ff1,zzz,16);
  58. };
  59. void LOutErr(LPCSTR s)
  60. {
  61.     MessageBox(hwnd,s,"Loading failed...",MB_ICONWARNING|MB_OK);
  62. };
  63. void SOutErr(LPCSTR s)
  64. {
  65.     MessageBox(hwnd,s,"Saving failed...",MB_ICONWARNING|MB_OK);
  66. };
  67. void SavePackArray(ResFile ff1,word defval,word* dest,int size){
  68.     word szs=0;
  69.     for(int i=0;i<size;i++)if(dest[i]!=defval)szs++;
  70.     RBlockWrite(ff1,&szs,2);
  71.     RBlockWrite(ff1,&defval,2);
  72.     for(i=0;i<size;i++)if(dest[i]!=defval){
  73.         RBlockWrite(ff1,&i,2);
  74.         RBlockWrite(ff1,&dest[i],2);
  75.     };
  76. };
  77. void LoadPackArray(ResFile ff1,word* dest,int size){
  78.     word szs;
  79.     word defv;
  80.     RBlockRead(ff1,&szs,2);
  81.     RBlockRead(ff1,&defv,2);
  82.     for(int i=0;i<size;i++)dest[i]=defv;
  83.     word ofst=0;
  84.     word vall;
  85.     for(i=0;i<szs;i++){
  86.         RBlockRead(ff1,&ofst,2);
  87.         RBlockRead(ff1,&vall,2);
  88.         dest[ofst]=vall;
  89.     };
  90. };
  91. void Nation::CloseNation(){
  92.     for(int i=0;i<NMon;i++){
  93.         if(Mon[i]){
  94.             Mon[i]->CloseGO();
  95.             free(Mon[i]);
  96.         };
  97.         if(PAble[i])free(PAble[i]);
  98.         PACount[i]=0;
  99.         if(CLSize[i])free(CLRef[i]);
  100.     };
  101.     NGidot=0;
  102.     NFarms=0;
  103.     NCOND=0;
  104.     if(NLmenus)free(Lmenus);
  105.     if(NWmenus)free(Wmenus);
  106.     if(NAmenus)free(Amenus);
  107.     if(NCmenus)free(Cmenus);
  108.     if(Animations)free(Animations);
  109.     if(Slides)free(Slides);
  110.     if(Finf)free(Finf);
  111.     for(i=0;i<NIcons;i++){
  112.         WIcon* icc=wIcons[i];
  113.         if(icc->Message)free(icc->Message);
  114.         if(icc->SubList)free(icc->SubList);
  115.         free(wIcons[i]);
  116.     };
  117.     //free upgrades
  118.     for(i=0;i<UPG.NUpgrades;i++){
  119.         if(UPG.utp1[i]->NLinks)free(UPG.utp1[i]->Links);
  120.         if(UPG.utp1[i]->NAuto)free(UPG.utp1[i]->AutoPerf);
  121.         free(UPG.utp1[i]);
  122.     };
  123. };
  124. void GeneralObject::CloseGO(){
  125.     if(Message)free(Message);
  126.     if(NUpgrades)free(Upg);
  127.     if(NIcons)free(IRefs);
  128. };
  129. void OneObject::CloseObject(){
  130.     if(NInside)free(Inside);
  131.     if(PathX)free(PathX);
  132.     if(PathY)free(PathY);
  133.     CPdestX=0;
  134.     CPdestY=0;
  135.     NIPoints=0;
  136.     CurIPoint=0;
  137.     ClearOrders();
  138.     if(InLineCom)FreeAsmLink();
  139.  
  140. };
  141. void UnLoading(){
  142.     for(int i=0;i<8;i++)NATIONS[i].CloseNation();
  143.     for(i=0;i<MaxObject;i++)if(Group[i]){
  144.         Group[i]->CloseObject();
  145.         Group[i]=NULL;
  146.     };
  147.     //closing multiple groups selection information 
  148.     for(i=0;i<80;i++){
  149.         if(int(SelSet[i].Member))free(SelSet[i].Member);
  150.         if(int(SelSet[i].SerialN))free(SelSet[i].SerialN);
  151.         SelSet[i].NMemb=0;
  152.     };
  153.     for(i=0;i<8;i++){
  154.         if(int(Selm[i]))free(Selm[i]);
  155.         if(int(SerN[i]))free(SerN[i]);
  156.         Selm[i]=NULL;
  157.         SerN[i]=NULL;
  158.         NSL[i]=0;
  159.     };
  160.     //flying objects clearing
  161.     for(i=0;i<64;i++)
  162.         for(int j=0;j<64;j++){
  163.             FlyCell* FC=&FlyMap[i][j];
  164.             FC->NFly=0;
  165.             for(int k=0;k<15;k++)FC->FlyList[k]=0xFFFF;
  166.         };
  167.     //walls clearing
  168.     memset(Links,255,sizeof Links);
  169.     memset(LIndex,255,sizeof LIndex);
  170.     for(i=0;i<GWALLS.MaxWall;i++){
  171.         WallCluster* WC=&GWALLS.GWC[i];
  172.         if(WC->Cells&&WC->ClusterSize)free(WC->Cells);
  173.     };
  174.     free(GWALLS.GWC);
  175.     GWALLS.MaxWall=1024;
  176.     GWALLS.GWC=new WallCluster[GWALLS.MaxWall];
  177.     memset(GWALLS.GWC,0,GWALLS.MaxWall*sizeof(WallCluster));
  178.     //clear flying objects
  179.     memset(EUsage,0,sizeof EUsage);
  180.     //clear magic
  181.     //cells inf clearing
  182.     memset(&TCInf[0][0],0,sizeof(TCInf));
  183.     NNuc=0;
  184.     memset(NucList,0,sizeof NucList);
  185.     memset(NucSN,0,sizeof NucSN);
  186.     memset(NDone,0,sizeof NDone);
  187.     SetSumms();
  188. };
  189. //SAVING...
  190. static int sfHeader='WSF2';
  191. int sfVersion;
  192. void SaveMap(ResFile ff1){
  193.     int i=0x1B46504D;
  194.     RBlockWrite(ff1,&i,4);            //dd Sign
  195.     SAVMES(ff1,"MAPSIZE");
  196.     RBlockWrite(ff1,&msx,4);        //dd msx
  197.     RBlockWrite(ff1,&msy,4);        //dd msy
  198.     i=0;
  199.     RBlockWrite(ff1,&i,4);
  200.     RBlockWrite(ff1,&i,4);
  201.     SAVMES(ff1,"TILEMAP");
  202.     for(i=0;i<msy;i++){
  203.         SAVMES1(ff1,"TMLINE:",i);
  204.         RBlockWrite(ff1,&tmap[i][0],msx);
  205.     };
  206.     SAVMES(ff1,"DEATHMAP");
  207.     SavePackArray(ff1,0xFFFF,&Died[0][0],65536);
  208. };
  209. extern bool BuildMode;
  210. void LoadMap(ResFile ff1)
  211. {
  212.     PromptTime=0;
  213.     MAXOBJECT=0;
  214.     memset(&fmap[0][0],0,sizeof fmap);
  215.     memset(Group,0,sizeof Group);
  216.     memset(&TrMap[0][0],0,sizeof TrMap);
  217.     memset(&LLock[0][0],0,sizeof LLock);
  218.     memset(&WLock[0][0],0,sizeof WLock);
  219.     memset(&WMap[0][0],0,sizeof WMap);
  220.     memset(&map[0][0],0,sizeof map);
  221.     memset(NLocks,0,sizeof NLocks);
  222.     BuildMode=false;
  223.     for(int i=0;i<maxmap;i++)
  224.     for(int j=0;j<maxmap;j++){
  225.         //map[i][j].BuildingID=65535;
  226.         Mops[j][i]=65535;
  227.         Died[j][i]=65535;
  228.         FlyMops[j][i]=65535;
  229.         //map[i][j].FlyID=65535;
  230.     };
  231.     RBlockRead(ff1,&i,4);
  232.     if (i!=0x1B46504D) LOutErr("Incorrect map file format.");
  233.     LOADMES(ff1);
  234.     RBlockRead(ff1,&msx,4);
  235.     RBlockRead(ff1,&msy,4);
  236.     RBlockRead(ff1,&i,4);
  237.     RBlockRead(ff1,&i,4);
  238.     LOADMES(ff1);
  239.     for(i=0;i<msy;i++){
  240.         LOADMES(ff1);
  241.         RBlockRead(ff1,&tmap[i][0],msx);
  242.     };
  243.     LOADMES(ff1);
  244.     LoadPackArray(ff1,&Died[0][0],65536);
  245.     for(i=0;i<msx;i++)for(int j=0;j<msy;j++){
  246.         byte k=Locking[tmap[j][i]];
  247.         if(k&1){
  248.             LLock[i+1][j+1]=1;
  249.             IncLock(j+1,i+1);
  250.             TrMap[i+1][j+1]=1;
  251.         };
  252.         //if(k&2)map[j][i].WaterLock=true;
  253.     };
  254.     for(i=0;i<=msx+1;i++){
  255.         TrMap[i][0]=2;
  256.         TrMap[i][msy+1]=2;
  257.         LLock[i][0]=2;
  258.         IncLock(0,i);
  259.         LLock[i][msy+1]=2;
  260.         IncLock(msy+1,i);
  261.         WMap[i][0]=2;
  262.         WMap[i][msy+1]=2;
  263.         WLock[i][0]=2;
  264.         WLock[i][msy+1]=2;
  265.         WMap[i][0]=2;
  266.         WMap[i][msy+2]=2;
  267.         WLock[i][0]=2;
  268.         WLock[i][msy+2]=2;
  269.  
  270.     };
  271.     for(i=0;i<msy+1;i++){
  272.         TrMap[0][i]=2;
  273.         TrMap[msx+1][i]=2;
  274.         LLock[0][i]=2;
  275.         IncLock(i,0);
  276.         LLock[msx+1][i]=2;
  277.         IncLock(i,msx+1);
  278.         WMap[0][i]=2;
  279.         WMap[msx+1][i]=2;
  280.         WLock[0][i]=2;
  281.         WLock[msx+1][i]=2;
  282.         WMap[0][i]=2;
  283.         WMap[msx+2][i]=2;
  284.         WLock[0][i]=2;
  285.         WLock[msx+2][i]=2;
  286.     };
  287.     //RSCRSizeX=RealLx;
  288.     //RSCRSizeY=RealLy;
  289.     //COPYSizeX=RealLx;
  290.     //smaplx=17;
  291.     //if(RSCRSizeY==768)smaplx=22;
  292.     //smaply=smaplx;
  293.     //smapx=COPYSizeX-(smaplx<<5)-32;
  294.     //smapy=(RSCRSizeY-(smaply<<5))>>1;
  295.     //smapx=7*32;
  296.     //smapy=28;
  297.     //smaplx=19;
  298.     //smaply=19;
  299.     //mapx=1;
  300.     //mapy=1;
  301.     //minix=32;
  302.     //miniy=32;
  303.     MiniMade=false;
  304.     //Nsel=0;    
  305.     CreateResMap();
  306.     CreateWaterMap();
  307.     CreateTZones();
  308.     CreateCMap();
  309.     InitRenderMap();
  310. };
  311. void SaveNations(ResFile ff1){
  312.     int tt=0x4954414E;//'NATI'
  313.     RBlockWrite(ff1,&tt,4);
  314.     SAVMES(ff1," NATSAVE");
  315.     byte nn=8;
  316.     RBlockWrite(ff1,&nn,1);
  317.     for(tt=0;tt<8;tt++){
  318.         SAVMES1(ff1," NATION: ",tt);
  319.         Nation* NT=&NATIONS[tt];
  320.         RBlockWrite(ff1,NT->SCRIPT,16);
  321.         RBlockWrite(ff1,&NT->NMask,1);
  322.         RBlockWrite(ff1,&NT->NNUM,1);
  323.         SAVMES1(ff1," MONSAMOUNT :",NT->NMon);
  324.         RBlockWrite(ff1,&NT->NMon,4);
  325.         //Informtion about monsters(GeneralObject)
  326.         for(int i=0;i<NT->NMon;i++){
  327.             GeneralObject* GO=NT->Mon[i];
  328.             Visuals* VS=(Visuals*)GO;
  329.             SAVMES1(ff1," NMONSTER:",i);
  330.             nn=GO->NoSearchVictim;
  331.             if(GO->NoAnswer)nn=nn|2;
  332.             if(GO->NeedNoHelp)nn=nn|4;
  333.             if(GO->Enabled)nn=nn|8;
  334.             RBlockWrite(ff1,&nn,1);
  335.             RBlockWrite(ff1,&VS->info.Basic.MaxShield,2);
  336.             RBlockWrite(ff1,&VS->info.Basic.MinDamage,2);
  337.             RBlockWrite(ff1,&VS->info.Basic.MaxDamage,2);
  338.             RBlockWrite(ff1,&VS->info.Basic.MaxLife,2);
  339.             RBlockWrite(ff1,&VS->info.Basic.AttackRange,2);
  340.         };
  341.         //Information about city
  342.         SAVMES(ff1,"CITYINFO");
  343.         City* CT=NT->CITY;
  344.         RBlockWrite(ff1,&CT->InX,34);
  345.         nn=CT->PresentProject;
  346.         if(CT->IntellectEnabled)nn|=2;
  347.         RBlockWrite(ff1,&nn,1);
  348.         if(CT->IntellectEnabled){
  349.             //Save AI properties if intellect is enabled
  350.             //1.Information about crowds(10+1 --defence)
  351.             for(i=0;i<11;i++){
  352.                 Crowd* CR=&CT->CROWDS[i];
  353.                 RBlockWrite(ff1,&CR->Amount,2);
  354.                 RBlockWrite(ff1,&CR->NI,1);
  355.                 RBlockWrite(ff1,&CR->MLSize,2);
  356.                 RBlockWrite(ff1,CR->MemList,CR->MLSize<<1);
  357.                 RBlockWrite(ff1,&CR->LastDx,23*4);
  358.                 RBlockWrite(ff1,CR->ForAtt,32*2);
  359.             };
  360.             //2.Enemy list
  361.             RBlockWrite(ff1,CT->EnemyList,32*2);
  362.             //End AI Statements
  363.         };
  364.         SAVMES(ff1,"UPGRADEINFO");
  365.         RBlockWrite(ff1,&NT->NGidot,4);
  366.         RBlockWrite(ff1,&NT->NFarms,4);
  367.         //Upgrades information
  368.         Upgrade* UP=&NT->UPG;
  369.         RBlockWrite(ff1,&UP->NUpgrades,4);
  370.         for(i=0;i<UP->NUpgrades;i++){
  371.             nn=UP->utp1[i]->Enabled;
  372.             RBlockWrite(ff1,&nn,1);
  373.             RBlockWrite(ff1,&UP->utp1[i]->Stage,2);
  374.         };
  375.         //end of upgrade information
  376.         //General AI statements
  377.         SAVMES(ff1,"GENERALAI");
  378.         RBlockWrite(ff1,&NT->CasheSize,4);
  379.         RBlockWrite(ff1,&NT->NationalAI,4);
  380.         RBlockWrite(ff1,&NT->SWP,sizeof NT->SWP);
  381.         //end of nation saving
  382.     };
  383. };
  384. bool LoadNations(ResFile ff1){
  385.     int tt;
  386.     RBlockRead(ff1,&tt,4);
  387.     if(tt!=0x4954414E){//'NATI'0x
  388.         LOutErr("Save file is corrupted.▀ φσ ΣεΩ≥ε≡ ∩ε save- ⌠αΘδα∞.");
  389.         return false;
  390.     };
  391.     LOADMES(ff1);
  392.     byte nn;
  393.     RBlockRead(ff1,&nn,1);
  394.     for(tt=0;tt<8;tt++){
  395.         LOADMES(ff1);
  396.         char stri[16];
  397.         Nation* NT=&NATIONS[tt];
  398.         RBlockRead(ff1,stri,16);
  399.         byte ms;
  400.         byte ni;
  401.         RBlockRead(ff1,&ms,1);
  402.         RBlockRead(ff1,&ni,1);
  403.         LoadNation(stri,ms,ni);
  404.         CITY[ni].CreateCity(20,20,ni);
  405.         LOADMES(ff1);
  406.         RBlockRead(ff1,&NT->NMon,4);
  407.         //Informtion about monsters(GeneralObject)
  408.         for(int i=0;i<NT->NMon;i++){
  409.             GeneralObject* GO=NT->Mon[i];
  410.             Visuals* VS=(Visuals*)GO;
  411.             LOADMES(ff1);
  412.             RBlockRead(ff1,&nn,1);
  413.             GO->NoSearchVictim=false;
  414.             GO->NoAnswer=false;
  415.             GO->NeedNoHelp=false;
  416.             GO->Enabled=false;
  417.             if(nn&1)GO->NoSearchVictim=true;
  418.             if(nn&2)GO->NoAnswer=true;
  419.             if(nn&4)GO->NeedNoHelp=true;
  420.             if(nn&8)GO->Enabled=true;
  421.             RBlockRead(ff1,&VS->info.Basic.MaxShield,2);
  422.             RBlockRead(ff1,&VS->info.Basic.MinDamage,2);
  423.             RBlockRead(ff1,&VS->info.Basic.MaxDamage,2);
  424.             RBlockRead(ff1,&VS->info.Basic.MaxLife,2);
  425.             RBlockRead(ff1,&VS->info.Basic.AttackRange,2);
  426.         };
  427.         //Information about city
  428.         LOADMES(ff1);
  429.         City* CT=NT->CITY;
  430.         RBlockRead(ff1,&CT->InX,34);
  431.         RBlockRead(ff1,&nn,1);
  432.         CT->PresentProject=false;
  433.         CT->IntellectEnabled=false;
  434.         if(nn&1)CT->PresentProject=true;
  435.         if(nn&2)CT->IntellectEnabled=true;
  436.         if(CT->IntellectEnabled){
  437.             //Load AI properties if intellect is enabled
  438.             //1.Information about crowds(10+1 --defence)
  439.             for(i=0;i<11;i++){
  440.                 Crowd* CR=&CT->CROWDS[i];
  441.                 RBlockRead(ff1,&CR->Amount,2);
  442.                 RBlockRead(ff1,&CR->NI,1);
  443.                 RBlockRead(ff1,&CR->MLSize,2);
  444.                 CR->MemList=new word[CR->MLSize];
  445.                 RBlockRead(ff1,CR->MemList,CR->MLSize<<1);
  446.                 RBlockRead(ff1,&CR->LastDx,23*4);
  447.                 RBlockRead(ff1,CR->ForAtt,32*2);
  448.             };
  449.             //2.Enemy list
  450.             RBlockRead(ff1,CT->EnemyList,32*2);
  451.             //End AI Statements
  452.         };
  453.         LOADMES(ff1);
  454.         RBlockRead(ff1,&NT->NGidot,4);
  455.         RBlockRead(ff1,&NT->NFarms,4);
  456.         //Upgrades information
  457.         Upgrade* UP=&NT->UPG;
  458.         RBlockRead(ff1,&UP->NUpgrades,4);
  459.         for(i=0;i<UP->NUpgrades;i++){
  460.             RBlockRead(ff1,&nn,1);
  461.             UP->utp1[i]->Enabled=nn;
  462.             RBlockRead(ff1,&UP->utp1[i]->Stage,2);
  463.         };
  464.         //end of upgrade information
  465.         //General AI statements
  466.         LOADMES(ff1);
  467.         RBlockRead(ff1,&NT->CasheSize,4);
  468.         RBlockRead(ff1,&NT->NationalAI,4);
  469.         RBlockRead(ff1,&NT->SWP,sizeof NT->SWP);
  470.         //end of nation loading
  471.     };
  472.     return true;
  473. };
  474. extern void BuildObjLink(OneObject* OB);
  475. extern void ProduceObjLink(OneObject* OB);
  476. extern void FlySendToLink(OneObject* OB);
  477. extern void FlyAttackLink(OneObject* OB);
  478. extern void SendInGroupLink(OneObject* OB);
  479. extern void SendToLink(OneObject* OB);
  480. extern void AttackObjLink(OneObject* OB);
  481. extern void ComplexAttackLink(OneObject* OB);
  482. extern void AttackPointLink(OneObject* OB);
  483. extern void MFLink(OneObject* OB);
  484. extern void PatrolLink(OneObject* OB);
  485. extern void TakeResLink(OneObject* OB);
  486. extern void BuildOnWaterLink(OneObject* OB);
  487. extern void GetOilLink(OneObject* OB);
  488. extern void TeleLink(OneObject* OB);
  489. extern void GoToTransportLink(OneObject* OB);
  490. extern void UnloadPassangersLink(OneObject* OB);
  491. extern void PerformUpgradeLink(OneObject* OB);
  492. extern void WSendToLink(OneObject* OB);
  493. extern void WAttackObjLink(OneObject* OB);
  494. extern void WMFLink(OneObject* OB);
  495. extern void BuildWallLink(OneObject* OB);
  496. extern void DamageWallLink(OneObject* OB);
  497. extern void ContinueAttackPointLink(OneObject* OBJ);
  498. extern void ContinueAttackWallLink(OneObject* OBJ);
  499. extern void UFOLink(OneObject* OB);
  500. extern void NuclearAttackLink(OneObject* OB);
  501. void WaitForRepairLink(OneObject* OBJ);
  502. #define OrdCount 28
  503. ReportFn* ORDLIST[OrdCount]={
  504.     &BuildObjLink,
  505.     &ProduceObjLink,
  506.     &FlySendToLink,
  507.     &FlyAttackLink,
  508.     &SendInGroupLink,
  509.     &SendToLink,
  510.     &AttackObjLink,
  511.     &ComplexAttackLink,
  512.     &AttackPointLink,
  513.     &MFLink,
  514.     &PatrolLink,
  515.     &TakeResLink,
  516.     &BuildOnWaterLink,
  517.     &GetOilLink,
  518.     &TeleLink,
  519.     &GoToTransportLink,
  520.     &UnloadPassangersLink,
  521.     &PerformUpgradeLink,
  522.     &WSendToLink,
  523.     &WAttackObjLink,
  524.     &WMFLink,
  525.     &BuildWallLink,
  526.     &DamageWallLink,
  527.     &ContinueAttackPointLink,
  528.     &ContinueAttackWallLink,
  529.     &UFOLink,
  530.     &NuclearAttackLink,
  531.     &WaitForRepairLink
  532. };
  533. int GetOrderKind(ReportFn* RF){
  534.     for(int i=0;i<OrdCount;i++)if(RF==ORDLIST[i])return i;
  535.     return -1;
  536. };
  537. ReportFn* GetOrderRef(int i){
  538.     if(i==-1||i>=OrdCount)return NULL;
  539.     return ORDLIST[i];
  540. };
  541. void SaveObjects(ResFile ff1){
  542.     int i=0x494A424F;//'OBJI'
  543.     int NObjects=0;
  544.     RBlockWrite(ff1,&i,4);
  545.     SAVMES(ff1," OBJECTSINFO");
  546.     for(i=0;i<MAXOBJECT;i++)if(Group[i])NObjects++;
  547.     RBlockWrite(ff1,&NObjects,4);
  548.     RBlockWrite(ff1,&MAXOBJECT,4);
  549.     //Information for every object
  550.     for(int tt=0;tt<MAXOBJECT;tt++){
  551.         OneObject* OB=Group[tt];
  552.         if(OB){
  553.             SAVMES1(ff1," OBJECT:",OB->Index);
  554.             RBlockWrite(ff1,&OB->Index,int(&OB->Media)-int(&OB->Index)+1);
  555.             int ca=int(OB->CurAnm)-int(OB->Nat->Animations);
  556.             RBlockWrite(ff1,&ca,4);
  557.             RBlockWrite(ff1,&OB->NInside,2);
  558.             if(OB->NInside){
  559.                 RBlockWrite(ff1,OB->Inside,OB->NInside<<1);
  560.             };
  561.             if(OB->Media==2){//Air unit only
  562.                 RBlockWrite(ff1,&OB->RealX,int(&OB->RealDir)-int(&OB->RealX)+1);
  563.             };
  564.             //saving index of selection group
  565.             int pp;
  566.             if(OB->GroupIndex)pp=div(int(OB->GroupIndex)-int(SelSet),sizeof SelGroup).quot;
  567.             else pp=255;
  568.             RBlockWrite(ff1,&pp,1);
  569.             SAVMES(ff1," ORDERINFO");
  570.             //Order information saving
  571.             //1. calculating orders
  572.             pp=0;
  573.             Order1* ORDR=OB->LocalOrder;
  574.             while(ORDR){
  575.                 pp++;
  576.                 ORDR=ORDR->NextOrder;
  577.             };
  578.             RBlockWrite(ff1,&pp,2);
  579.             if(pp){
  580.                 //2.saving order information
  581.                 Order1 ORD1;
  582.                 ORDR=OB->LocalOrder;
  583.                 ORD1=*OB->LocalOrder;
  584.                 while(ORDR){
  585.                     ORD1.NextOrder=NULL;
  586.                     ORD1.DoLink=(ReportFn*)(GetOrderKind(ORDR->DoLink));
  587.                     assert(int(ORD1.DoLink)!=-1);
  588.                     RBlockWrite(ff1,&ORD1,sizeof ORD1);
  589.                     ORDR=ORDR->NextOrder;
  590.                     if(ORDR)ORD1=*ORDR;
  591.                 };
  592.             };
  593.             //Priory level
  594.             RBlockWrite(ff1,&OB->PrioryLevel,1);
  595.         };
  596.     };
  597. };
  598. void LoadObjects(ResFile ff1){
  599.     //sigature checking
  600.     int i;
  601.     RBlockRead(ff1,&i,4);
  602.     LOADMES(ff1);
  603.     if(i!=0x494A424F)LOutErr("SAVE file is corrupted. ╚π≡√ φσ ß≤Σσ≥.");//'OBJI'
  604.     int NObjects=0;
  605.     RBlockRead(ff1,&NObjects,4);
  606.     RBlockRead(ff1,&MAXOBJECT,4);
  607.     //Information for every object
  608.     for(int tt=0;tt<NObjects;tt++){
  609.         word Indx;
  610.         LOADMES(ff1);
  611.         RBlockRead(ff1,&Indx,2);
  612.         Group[Indx]=OBJECTS+Indx;//assign pointer
  613.         OneObject* OB=Group[Indx];
  614.         OB->Index=Indx;
  615.         //init path information
  616.         OB->PathX=NULL;
  617.         OB->PathY=NULL;
  618.         OB->NIPoints=0;
  619.         OB->CurIPoint=0;
  620.         OB->CPdestX=0;
  621.         OB->CPdestY=0;
  622.         //Loading header information
  623.         RBlockRead(ff1,&OB->NIndex,int(&OB->Media)-int(&OB->NIndex)+1);
  624.     //Default object settings
  625.         int x=OB->x;
  626.         int y=OB->y;
  627.         //1.Nation reference
  628.         OB->Nat=&NATIONS[OB->NNUM];
  629.         Nation* NT=OB->Nat;
  630.         //2.General object reference
  631.         OB->Ref.General=NT->Mon[OB->NIndex];
  632.         GeneralObject* GO=OB->Ref.General;
  633.         int ca;
  634.         RBlockRead(ff1,&ca,4);
  635.         OB->CurAnm=(Octant*)(int(NT->Animations)+ca);
  636.         //3.Inside objects
  637.         if(OB->Transport)OB->Inside=new word[6];
  638.         RBlockRead(ff1,&OB->NInside,2);
  639.         if(OB->NInside)RBlockRead(ff1,OB->Inside,OB->NInside<<1);
  640.         OB->TimeInside=NULL;
  641.         //4. Other default information
  642.         OB->Wars=NULL;//No Legion information
  643.         OB->InLineCom=NULL;
  644.         OB->LineOffset=0;
  645.         //5.Animation registers
  646.         memset(&(OB->ARegs),0,sizeof OB->ARegs);
  647.         //6.Weapon assignment
  648.         OB->Weap=GO->Weap;
  649.         //7.Land/Water/Air information
  650.         OB->LoadAnimation(0,0,0);
  651.         Cell8x8* CELL=&TCInf[OB->NNUM][y>>2][x>>2];
  652.         CELL->UnitsAmount[GO->Kind]++;
  653.         if(GO->OnWater){
  654.             if(!OB->Sdoxlo){
  655.                 Mops[y][x]=Indx;
  656.                 WLock[y][x]=true;
  657.             };
  658.             //WMap[y][x]=1;
  659.         }else if(GO->OnAir){
  660.             RBlockRead(ff1,&OB->RealX,int(&OB->RealDir)-int(&OB->RealX)+1);
  661.             OB->LoadAnimation(0,0,0);//stand=motion animation
  662.             OB->LoadAnimation(1,2,0);//attack
  663.             OB->LoadAnimation(2,3,0);//death
  664.             if(!OB->Sdoxlo)FlyMops[y][x]=OB->Index;
  665.             int cx=(OB->RealX-256)>>11;
  666.             int cy=(OB->RealY-256)>>11;
  667.             FlyCell* FC=&FlyMap[cy][cx];
  668.             for(int k=0;FC->FlyList[k]!=0xFFFF;k++);
  669.             FC->NFly++;
  670.             FC->FlyList[k]=OB->Index;
  671.         }else{
  672.             if(GO->cpbBuilding){
  673.                 if(!OB->Sdoxlo){
  674.                     for(byte dx=0;dx<OB->Lx;dx++)
  675.                         for(byte dy=0;dy<OB->Lx;dy++){
  676.                             LLock[y+dy][x+dx]=1;
  677.                             IncLock(x+dx,y+dy);
  678.                             TrMap[y+dy][x+dx]=1;
  679.                             WMap[y+dy][x+dx]=1;
  680.                             WLock[y+dy][x+dx]=1;
  681.                             Mops[y+dy][x+dx]=Indx;
  682.                         };
  683.                 };
  684.             }else{
  685.                 if(!OB->Sdoxlo){
  686.                     Mops[y][x]=Indx;    
  687.                     LLock[y][x]=true;
  688.                     IncLock(x,y);
  689.                 };
  690.             };
  691.     //end of default settings
  692.         };
  693.         
  694.         //loading index of selection group
  695.         int pp=0;
  696.         RBlockRead(ff1,&pp,1);
  697.         if(pp==255)OB->GroupIndex=NULL;
  698.         else OB->GroupIndex=SelSet+pp;
  699.         //Order information loading
  700.         LOADMES(ff1);
  701.         //1. calculating orders
  702.         RBlockRead(ff1,&pp,2);//number of orders
  703.         Order1 ORD1;
  704.         Order1* PORD=NULL;
  705.         for(int j=0;j<pp;j++){
  706.             //loading orders
  707.             RBlockRead(ff1,&ORD1,sizeof ORD1);
  708.             Order1* ORDR=GetOrdBlock();
  709.             if(!j)OB->LocalOrder=ORDR;
  710.  
  711.             *ORDR=ORD1;
  712.             ORDR->NextOrder=NULL;
  713.             if(PORD)PORD->NextOrder=ORDR;
  714.             PORD=ORDR;
  715.             //DoLink assignment
  716.             ORDR->DoLink=ORDLIST[int(ORDR->DoLink)];
  717.         };
  718.         //Priory level
  719.         RBlockRead(ff1,&OB->PrioryLevel,1);
  720.     };
  721. };
  722. void SaveSelection(ResFile ff1){
  723.     int i='SELI';
  724.     RBlockWrite(ff1,&i,4);
  725.     SAVMES(ff1," SELECTINFO");
  726.     for(i=0;i<80;i++){
  727.         SelGroup* SG=&SelSet[i];
  728.         RBlockWrite(ff1,&SG->NMemb,(sizeof SelGroup)-8);
  729.         if(SG->NMemb){
  730.             RBlockWrite(ff1,SG->Member,SG->NMemb<<1);
  731.             RBlockWrite(ff1,SG->SerialN,SG->NMemb<<1);
  732.         };
  733.     };
  734.     for(i=0;i<8;i++){
  735.         RBlockWrite(ff1,&NSL[i],2);
  736.         if(NSL[i]){
  737.             RBlockWrite(ff1,Selm[i],NSL[i]<<1);
  738.             RBlockWrite(ff1,SerN[i],NSL[i]<<1);
  739.         };
  740.     };
  741. };
  742. void LoadSelection(ResFile ff1){
  743.     int i;
  744.     RBlockRead(ff1,&i,4);
  745.     LOADMES(ff1);
  746.     if(i!='SELI')LOutErr("Save file is corrupted.");
  747.     for(i=0;i<80;i++){
  748.         SelGroup* SG=&SelSet[i];
  749.         RBlockRead(ff1,&SG->NMemb,(sizeof SelGroup)-8);
  750.         if(SG->NMemb){
  751.             SG->Member=new word[SG->NMemb];
  752.             SG->SerialN=new word[SG->NMemb];
  753.             RBlockRead(ff1,SG->Member,SG->NMemb<<1);
  754.             RBlockRead(ff1,SG->SerialN,SG->NMemb<<1);
  755.         }else{
  756.             SG->Member=NULL;
  757.             SG->SerialN=NULL;
  758.         };
  759.     };
  760.     for(i=0;i<8;i++){
  761.         RBlockRead(ff1,&NSL[i],2);
  762.         if(NSL[i]){
  763.             Selm[i]=new word[NSL[i]];
  764.             SerN[i]=new word[NSL[i]];
  765.             RBlockRead(ff1,Selm[i],NSL[i]<<1);
  766.             RBlockRead(ff1,SerN[i],NSL[i]<<1);
  767.         }else{
  768.             Selm[i]=NULL;
  769.             SerN[i]=NULL;
  770.         };
  771.     };
  772. };
  773. void SaveWalls(ResFile ff1){
  774.     int i='LLAW';
  775.     RBlockWrite(ff1,&i,4);
  776.     //SAVMES(ff1," WALLSINFO");
  777.     RBlockWrite(ff1,&GWALLS.MaxWall,4);
  778.     int cln=0;
  779.     for(i=0;i<GWALLS.MaxWall;i++)if(GWALLS.GWC[i].ClusterSize)cln++;
  780.     RBlockWrite(ff1,&cln,4);
  781.     for(i=0;i<GWALLS.MaxWall;i++)if(GWALLS.GWC[i].ClusterSize){
  782.         WallCluster* WC=&GWALLS.GWC[i];
  783.         RBlockWrite(ff1,&i,4);
  784.         RBlockWrite(ff1,&WC->ClusterSize,4);
  785.         RBlockWrite(ff1,&WC->OwnerID,6);
  786.         RBlockWrite(ff1,WC->Cells,WC->ClusterSize*sizeof(WallCell));
  787.     };
  788.     SavePackArray(ff1,0xFFFF,&Links[0][0],65536);
  789.     SavePackArray(ff1,0xFFFF,&LIndex[0][0],65536);
  790.     SAVMES(ff1," RESOURCES");
  791.     RBlockWrite(ff1,&RESRC[0][0],sizeof RESRC);
  792.     RBlockWrite(ff1,&RESADD[0][0],sizeof RESADD);
  793.     RBlockWrite(ff1,&MAXOBJECT,4);
  794. };
  795. void LoadWalls(ResFile ff1){
  796.     int i;
  797.     RBlockRead(ff1,&i,4);
  798.     //LOADMES(ff1);
  799.     if(i!='LLAW')LOutErr("Save file is corrupted.");
  800.     RBlockRead(ff1,&GWALLS.MaxWall,4);
  801.     free(GWALLS.GWC);
  802.     GWALLS.GWC=new WallCluster[GWALLS.MaxWall];
  803.     memset(GWALLS.GWC,0,GWALLS.MaxWall*sizeof(WallCluster));
  804.     int cln;
  805.     int iii;
  806.     RBlockRead(ff1,&cln,4);
  807.     for(i=0;i<cln;i++){
  808.         RBlockRead(ff1,&iii,4);
  809.         WallCluster* WC=&GWALLS.GWC[iii];
  810.         RBlockRead(ff1,&WC->ClusterSize,4);
  811.         RBlockRead(ff1,&WC->OwnerID,6);
  812.         WC->Cells=new WallCell[WC->ClusterSize];
  813.         RBlockRead(ff1,WC->Cells,WC->ClusterSize*sizeof(WallCell));
  814.     };
  815.     LoadPackArray(ff1,&Links[0][0],65536);
  816.     LoadPackArray(ff1,&LIndex[0][0],65536);
  817. };
  818. extern Nation WEP;
  819. void SaveAnmObj(ResFile ff1){
  820.     SAVMES(ff1," ANIMATEINFO");
  821.     RBlockWrite(ff1,&EUsage[0],8192);
  822.     SAVMES(ff1," ANIMATEMAIN");
  823.     for(int i=0;i<8192;i++){
  824.         if(EUsage[i]){
  825.             SAVMES1(ff1," ANMOBJECT:",i);
  826.             AnmObject AO=*GAnm[i];
  827.             if(AO.Sender){
  828.                 AO.Sender=(OneObject*)(AO.Sender->Index);
  829.             }else{
  830.                 AO.Sender=(OneObject*)(-1);
  831.             };
  832.             int nwp=1024;
  833.             for(int cwp=0;WPLIST[cwp]!=AO.Wpn&&cwp<nwp;cwp++);
  834.             assert(cwp<nwp);
  835.             AO.Wpn=(Weapon*)cwp;
  836.             RBlockWrite(ff1,&AO,sizeof AO);
  837.         };
  838.     };
  839. };
  840. void LoadAnmObj(ResFile ff1){
  841.     LOADMES(ff1);
  842.     RBlockRead(ff1,&EUsage[0],8192);
  843.     LOADMES(ff1);
  844.     AnmObject AO;
  845.     for(int i=0;i<8192;i++){
  846.         if(EUsage[i]){
  847.             LOADMES(ff1);
  848.             RBlockRead(ff1,&AO,sizeof AO);
  849.             int sen=int(AO.Sender);
  850.             if(sen!=-1)AO.Sender=Group[sen];
  851.             else AO.Sender=NULL;
  852.             AO.Wpn=WPLIST[int(AO.Wpn)];
  853.             Octant* OC=AO.Wpn->Vis->lpFAnim[0].Anm;
  854.             if(AO.Wpn->Vis->cpbRotation)
  855.                 if(AO.Direction<5)AO.Kino=OC[AO.Direction].Movie;
  856.             else AO.Kino=OC[8-AO.Direction].Movie;
  857.             else AO.Kino=OC->Movie;
  858.             *GAnm[i]=AO;
  859.         };
  860.     };
  861. };
  862. typedef void SWHandle(StrangeWeapon* SW);
  863. void HandleHugeBomb(StrangeWeapon* SW);
  864. void HandleFireSea(StrangeWeapon* SW);
  865. void HandleBlizzard(StrangeWeapon* SW);
  866. void HandleMExplosion(StrangeWeapon* SW);
  867. void HandleMExplosion1(StrangeWeapon* SW);
  868. void HandleFireWall(StrangeWeapon* SW);
  869. void HandleSuperVision(StrangeWeapon* SW);
  870. void HandleFlyUP(StrangeWeapon* SW);
  871. void HandleNucl(StrangeWeapon* SW);
  872. void HandleFog(StrangeWeapon* SW);
  873.  
  874. #define SWPCOUNT 10
  875. SWHandle* STRWEP[SWPCOUNT]={
  876.     &HandleHugeBomb,
  877.     &HandleFireSea,
  878.     &HandleBlizzard,
  879.     &HandleMExplosion,
  880.     &HandleMExplosion1,
  881.     &HandleFireWall,
  882.     &HandleSuperVision,
  883.     &HandleFlyUP,
  884.     &HandleNucl,
  885.     &HandleFog
  886. };
  887. int GetMagNum(SWHandle* SW){
  888.     for(int i=0;i<SWPCOUNT&&SW!=STRWEP[i];i++);
  889.     assert(i<SWPCOUNT);
  890.     return i;
  891. };
  892. void SaveMagic(ResFile ff1){
  893.     bool WPIND[64];
  894.     SAVMES(ff1," MAGIC");
  895.     StrangeWeapon SWPN;
  896.     for(int i=0;i<64;i++)if(SWEAP[i].Enabled)WPIND[i]=1;
  897.     else WPIND[i]=0;
  898.     RBlockWrite(ff1,&WPIND[0],64);
  899.     for(i=0;i<64;i++)if(WPIND[i]){
  900.         SAVMES1(ff1," MAGOBJ:",i);
  901.         SWPN=SWEAP[i];
  902.         SWPN.SWH=(SWHandle*)GetMagNum(SWPN.SWH);
  903.         if(WPIND[i])RBlockWrite(ff1,&SWPN,sizeof SWPN);
  904.     };
  905. };
  906. void LoadMagic(ResFile ff1){
  907.     LOADMES(ff1);
  908.     bool WPIND[64];
  909.     RBlockRead(ff1,&WPIND[0],64);
  910.     StrangeWeapon SWPN;
  911.     for(int i=0;i<64;i++)if(WPIND[i]){
  912.         LOADMES(ff1);
  913.         RBlockRead(ff1,&SWPN,sizeof SWPN);
  914.         SWPN.SWH=(SWHandle*)STRWEP[int(SWPN.SWH)];
  915.         SWEAP[i]=SWPN;
  916.     }else{
  917.         SWEAP[i].Enabled=false;
  918.     };
  919. };
  920. extern word rpos;
  921. extern word NPlayers;
  922. void SaveGame(char* fnm,char* Messtr,int ID){
  923.     ResFile ff1=RRewrite(fnm);
  924.     RBlockWrite(ff1,&sfHeader,4);
  925.     RBlockWrite(ff1,&sfVersion,4);
  926.     RBlockWrite(ff1,&ID,4);
  927.     RBlockWrite(ff1,&NPlayers,2);
  928.     int sl=strlen(Messtr)+1;
  929.     RBlockWrite(ff1,&sl,1);
  930.     RBlockWrite(ff1,Messtr,sl);
  931.     RBlockWrite(ff1,&mapx,4);
  932.     RBlockWrite(ff1,&mapy,4);
  933.     SaveMap(ff1);
  934.     SaveNations(ff1);
  935.     SaveObjects(ff1);
  936.     SaveSelection(ff1);
  937.     SaveWalls(ff1);
  938.     RBlockWrite(ff1,&TCInf[0][0],sizeof(TCInf));
  939.     SaveAnmObj(ff1);
  940.     SaveMagic(ff1);
  941.     RBlockWrite(ff1,&MyNation,4);
  942.     RBlockWrite(ff1,&rpos,2);
  943.     RBlockWrite(ff1,NucList,sizeof NucList);
  944.     RBlockWrite(ff1,NucSN,sizeof NucSN);
  945.     RBlockWrite(ff1,NDone,sizeof NDone);
  946.     RBlockWrite(ff1,&NNuc,sizeof NNuc);
  947.     RClose(ff1);
  948. };
  949. void LoadGame(char* fnm){
  950.     //assert(_CrtCheckMemory());
  951.     ResFile ff1=RReset(fnm);
  952.     int i,y;
  953.     UnLoading();
  954.     RBlockRead(ff1,&i,4);
  955.     if(i!=sfHeader){
  956.         RClose(ff1);
  957.         return;
  958.     };
  959.     RBlockRead(ff1,&i,4);
  960.     if(i!=sfVersion){
  961.         RClose(ff1);
  962.         return;
  963.     };
  964.     RBlockRead(ff1,&i,4);
  965.     RBlockRead(ff1,&y,2);
  966.     int sl=0;
  967.     RBlockRead(ff1,&sl,1);
  968.     RBlockRead(ff1,GameName,sl);
  969.     RBlockRead(ff1,&mapx,4);
  970.     RBlockRead(ff1,&mapy,4);
  971.     LoadMap(ff1);
  972.     LoadNations(ff1);
  973.     LoadObjects(ff1);
  974.     LoadSelection(ff1);
  975.     LoadWalls(ff1);
  976.     LOADMES(ff1);
  977.     RBlockRead(ff1,&RESRC[0][0],sizeof RESRC);
  978.     RBlockRead(ff1,&RESADD[0][0],sizeof RESADD);
  979.     RBlockRead(ff1,&MAXOBJECT,4);
  980.     RBlockRead(ff1,&TCInf[0][0],sizeof(TCInf));
  981.     LoadAnmObj(ff1);
  982.     LoadMagic(ff1);
  983.     RBlockRead(ff1,&MyNation,4);
  984.     RBlockRead(ff1,&rpos,2);
  985.     RBlockRead(ff1,NucList,sizeof NucList);
  986.     RBlockRead(ff1,NucSN,sizeof NucSN);
  987.     RBlockRead(ff1,NDone,sizeof NDone);
  988.     RBlockRead(ff1,&NNuc,sizeof NNuc);
  989.     RClose(ff1);
  990.     //assert(_CrtCheckMemory());
  991. };