home *** CD-ROM | disk | FTP | other *** search
/ WarCraft 2000 - Nuclear Epidemic / W2000.nrg / SOURCE.War2000 / Nature.cpp < prev    next >
C/C++ Source or Header  |  1998-11-13  |  23KB  |  1,086 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 "TopZones.h"
  12. #include <assert.h>
  13. #include "MapEdit.h"
  14. #include "3DSurf.h"
  15. #include "GSound.h"
  16. Nation NATUR;
  17. void FindEmptyPoint(byte* x,byte* y);
  18. byte rtmap[256][256];//resource type map
  19. byte ramap[256][256];//resource amount map
  20. int RESRC[8][8];
  21. int RESADD[8][8];
  22. OneSlide OILOC;
  23. word OILMAP[128][128];
  24. const int drrn[9]={7,6,5,0,0,4,1,2,3};
  25. class ResDiscr{
  26. public:
  27.     bool Enabled;
  28.     char Name[32];
  29.     byte Amount;
  30.     byte MotionKind;
  31.     byte WorkKind;
  32.     byte Portion;
  33.     int AnmStandKind;
  34.     int AnmGoKind;
  35.     int Multi;
  36.     int Tiles [16][4];
  37.     ResDiscr();
  38. };
  39. byte TRType[256];
  40. byte TRMask[256];
  41. ResDiscr::ResDiscr(){
  42.     Enabled=false;
  43.     Amount=0;
  44.     Portion=0;
  45.     MotionKind=0;
  46.     WorkKind=0;
  47.     Name[0]=0;
  48.     AnmStandKind=0;
  49.     AnmGoKind=1;
  50.     memset(&TRType,0,256);
  51.     memset(&TRMask,0,256);
  52. };
  53. ResDiscr RDS[8];
  54. void Errr(LPCSTR s)
  55. {
  56.     MessageBox(hwnd,s,"Nature loading failed...",MB_ICONWARNING|MB_OK);
  57.     assert(false);
  58. };
  59. void LoadRDS(){
  60.     //NATUR.CreateNation("NATUR",255,255);
  61.     //OILOC=*NATUR.Mon[0]->lpFAnim->Anm->Movie;
  62.     memset(&OILMAP[0][0],0,sizeof OILMAP);
  63.     memset(&RESRC[0][0],0,64*4);
  64.     memset(&RESADD[0][0],0,64*4);
  65.     for(int h=0;h<8;h++){
  66.         RESRC[h][1]=5000;
  67.     };
  68.     FILE* f=fopen("nres.dat","r");
  69.     if(!int(f)){
  70.         Errr("Could not find NRES.DAT");
  71.         return;
  72.     };
  73.     bool eoff=false;
  74.     char s1[16];
  75.     int    z0,z1,z2,z3,z4,z5,z6,z7;
  76.     int    mode=0;
  77.     do{
  78.         switch(mode){
  79.         case 0:
  80.             fscanf(f,"%s",s1);
  81.             if(!strcmp(s1,"[CELLS]"))mode=1;
  82.  
  83.             else{
  84.                 fscanf(f,"%d%d",&z0,&z1);
  85.                 strcpy(RDS[z0].Name,s1);
  86.                 RDS[z0].Enabled=true;
  87.                 for(z3=0;z3<8;z3++)RESRC[z3][z0]=z1;
  88.             };
  89.             break;
  90.         case 1:
  91.             fscanf(f,"%s%d%d%d%d%d%d%d%d",s1,&z0,&z1,&z2,&z3,&z4,&z5,&z6,&z7);
  92.             if(!strcmp(s1,"[NEW]")){
  93.                 RDS[z0].Enabled=true;
  94.                 RDS[z0].MotionKind=z1;
  95.                 RDS[z0].WorkKind=z2;
  96.                 RDS[z0].Amount=z3;
  97.                 RDS[z0].Portion=z4;
  98.                 RDS[z0].Multi=z5;
  99.                 RDS[z0].AnmStandKind=z6;
  100.                 RDS[z0].AnmGoKind=z7;
  101.                 for(z5=0;z5<16;z5++){
  102.                     fscanf(f,"%d%d%d%d",&z1,&z2,&z3,&z4);
  103.                     RDS[z0].Tiles[z5][0]=z1;
  104.                     RDS[z0].Tiles[z5][1]=z2;
  105.                     RDS[z0].Tiles[z5][2]=z3;
  106.                     RDS[z0].Tiles[z5][3]=z4;
  107.                     TRType[z1]=byte(z0);
  108.                     TRMask[z1]=byte(z5);
  109.                     TRType[z2]=byte(z0);
  110.                     TRMask[z2]=byte(z5);
  111.                     TRType[z3]=byte(z0);
  112.                     TRMask[z3]=byte(z5);
  113.                     TRType[z4]=byte(z0);
  114.                     TRMask[z4]=byte(z5);
  115.                 };
  116.             }else mode=2;
  117.             break;
  118.         };
  119.     }while(mode!=2);
  120.     fclose(f) ;
  121. };
  122. void DefResource(int i,int j){
  123.     if(i>1&&j>1&&i<msx&&j<msy){
  124.         int til=int(tmap[i-1][j-1]);
  125.             byte msk=TRMask[til];
  126.             byte kind=TRType[til];
  127.             rtmap[j][i]=0;
  128.             rtmap[j+1][i]=0;
  129.             rtmap[j][i+1]=0;
  130.             rtmap[j+1][i+1]=0;
  131.             ramap[j][i]=0;
  132.             ramap[j+1][i]=0;
  133.             ramap[j][i+1]=0;
  134.             ramap[j+1][i+1]=0;
  135.             if(kind!=0){
  136.                 if(msk&1){
  137.                     rtmap[j][i]=kind;
  138.                     ramap[j][i]=RDS[kind].Amount-(rando()&31);
  139.                 };
  140.                 if(msk&2){
  141.                     rtmap[j][i+1]=kind;
  142.                     ramap[j][i+1]=RDS[kind].Amount-(rando()&31);
  143.                 };
  144.                 if(msk&4){
  145.                     rtmap[j+1][i]=kind;
  146.                     ramap[j+1][i]=RDS[kind].Amount-(rando()&31);
  147.                 };
  148.                 if(msk&8){
  149.                     rtmap[j+1][i+1]=kind;
  150.                     ramap[j+1][i+1]=RDS[kind].Amount-(rando()&31);
  151.                 };
  152.             };
  153.     };
  154. };
  155. void CreateResMap(){
  156.     memset(&rtmap[0][0],0,65536);
  157.     memset(&ramap[0][0],0,65536);
  158.     for(int i=1;i<msx;i++)
  159.         for(int j=1;j<msy;j++){
  160.             int til=int(tmap[i-1][j-1]);
  161.             byte msk=TRMask[til];
  162.             byte kind=TRType[til];
  163.             if(kind!=0){
  164.                 if(msk&1){
  165.                     rtmap[j][i]=kind;
  166.                     ramap[j][i]=RDS[kind].Amount-(rando()&31);
  167.                 };
  168.                 if(msk&2){
  169.                     rtmap[j][i+1]=kind;
  170.                     ramap[j][i+1]=RDS[kind].Amount-(rando()&31);
  171.                 };
  172.                 if(msk&4){
  173.                     rtmap[j+1][i]=kind;
  174.                     ramap[j+1][i]=RDS[kind].Amount-(rando()&31);
  175.                 };
  176.                 if(msk&8){
  177.                     rtmap[j+1][i+1]=kind;
  178.                     ramap[j+1][i+1]=RDS[kind].Amount-(rando()&31);
  179.                 };
  180.             };
  181.         };
  182. };
  183. void CreateSurface(byte x,byte y,byte rk){
  184.     byte dd=0;
  185.     if(ramap[y][x])dd+=1;
  186.     if(ramap[y][x+1])dd+=2;
  187.     if(ramap[y+1][x])dd+=4;
  188.     if(ramap[y+1][x+1])dd+=8;
  189.     //byte rk=rtmap[y][x];
  190.     int til=RDS[rk].Tiles[dd][rando()&3];
  191.     if(dd==0){
  192.         TrMap[y][x]=0;
  193.         LLock[y][x]=0;
  194.         DecLock(x,y);
  195.         PutZCell(x,y);
  196.     };
  197.     word tt=tmap[x-1][y-1];
  198.     if(tt!=til){
  199.         tmap[x-1][y-1]=byte(til);
  200.         ClearRender(x,y);
  201.     };
  202. };
  203. byte TakeResource(byte x,byte y,byte rk){
  204.     byte rt=rtmap[y][x]; 
  205.     byte ra=ramap[y][x];
  206.     if(ra>0){
  207.         ramap[y][x]--;
  208.         if(ra==1){
  209.             if(x>1&&y>1)CreateSurface(x-1,y-1,rk);
  210.             if(x>1)CreateSurface(x-1,y,rk);
  211.             if(y>1)CreateSurface(x,y-1,rk);
  212.             CreateSurface(x,y,rk);
  213.             if(rk==1)CMap[y][x]=1;
  214.             else CMap[y][x]=0;
  215.             rtmap[y][x]=0;
  216.             //PutZCell(x,y);
  217.         };
  218.         return 1;
  219.     };
  220.     return 0;
  221. };
  222. byte GetResourceKind(byte x,byte y){
  223.     if(ramap[y][x])return rtmap[y][x];
  224.     if(ramap[y+1][x])return rtmap[y+1][x];
  225.     if(ramap[y][x+1])return rtmap[y][x+1];
  226.     if(ramap[y+1][x+1])return rtmap[y+1][x+1];
  227.     return 0;
  228. };
  229. int TakeResFromCell(byte x,byte y){
  230.     byte rk=GetResourceKind(x,y);
  231.     if(rk==0)return 0;
  232.     int rr=TakeResource(x,y,rk);
  233.     rr+=TakeResource(x,y+1,rk);
  234.     rr+=TakeResource(x+1,y,rk);
  235.     rr+=TakeResource(x+1,y+1,rk);
  236.     return rr;
  237. };
  238. //Pseudo-local variables
  239. byte zx,zy,sx,sy;
  240. bool RAble(byte x,byte y,ZType zz){
  241.     if(zx<x)sx=x-1;else sx=x;
  242.     if(zy<y)sy=y-1;else sy=y;
  243.     if(RZAMap[sy][sx]!=zz)return false;
  244.     FindEmptyPoint(&sx,&sy);
  245.     if(sx) return true;else return false;
  246. };
  247. extern int COUNTER;
  248. bool FindResource(byte* xx,byte* yy,byte Radius,byte kind,ZType zz){
  249.     byte x1=*xx;
  250.     byte y1=*yy;
  251.     zx=x1;
  252.     zy=y1;
  253.     if(x1==0||y1==0)return false;
  254.     byte x0=x1;
  255.     byte y0=y1;
  256.     x1++;
  257.     y1++;
  258.     byte xr=0;
  259.     byte yr=0;
  260.     byte r=Radius;
  261.     byte* pt;
  262.     while(r>0){
  263.         byte dx=x1-x0;
  264.         byte dy=y1-y0;
  265.         xr=x0;yr=y0;
  266.         pt=(byte*)(int(rtmap)+x0+(int(y0)<<8));
  267.         for(byte i=0;i<dx;i++){
  268.             if(*pt==kind&&RAble(xr,yr,zz))goto FRes;
  269.             pt++;
  270.             xr++;
  271.         };
  272.         for(i=0;i<dy;i++){
  273.             if(*pt==kind&&RAble(xr,yr,zz))goto FRes;
  274.             pt+=256;
  275.             yr++;
  276.         };
  277.         for(i=0;i<dx;i++){
  278.             if(*pt==kind&&RAble(xr,yr,zz))goto FRes;
  279.             pt--;
  280.             xr--;
  281.         };
  282.         for(i=0;i<dy;i++){
  283.             if(*pt==kind&&RAble(xr,yr,zz))goto FRes;
  284.             pt-=256;
  285.             yr--;
  286.         };
  287.         if(x0>1)x0--;
  288.         if(y0>1)y0--;
  289.         if(x1<msx)x1++;
  290.         if(y1<msy)y1++;
  291.         r--;
  292.     };
  293.     return false;
  294. FRes:
  295.     *xx=sx;
  296.     *yy=sy;
  297.     return true;
  298. };
  299. /*
  300. bool CheckNearRes(byte* xx,byte* yy,byte kind){
  301.     byte x=*xx;
  302.     byte y=*yy;
  303.     if(x==0||y==0)return false;
  304.     __asm{
  305.         xor        eax,eax
  306.         mov        al,x
  307.         mov        ah,y
  308.         mov        bl,kind
  309.         add        eax,offset rtmap
  310.         cmp        [eax-256],bl
  311.         jne        qw1
  312.         dec        y
  313.         jmp        qw_end
  314. qw1:    cmp        [eax-255],bl
  315.         jne        qw2
  316.         dec        y
  317.         jmp        qw_end
  318. qw2:    cmp        [eax+2],bl
  319.         jne        qw3
  320.         inc        x
  321.         jmp        qw_end
  322. qw3:    cmp        [eax+258],bl
  323.         jne        qw4
  324.         inc        x
  325.         jmp        qw_end
  326. qw4:    cmp        [eax-1],bl
  327.         jne        qw5
  328.         dec        x
  329.         jmp        qw_end
  330. qw5:    cmp        [eax+255],bl
  331.         jne        qw6
  332.         dec        x
  333.         jmp        qw_end
  334. qw6:    cmp        [eax+512],bl
  335.         jne        qw7
  336.         inc        y
  337.         jmp        qw_end
  338. qw7:    cmp        [eax+513],bl
  339.         jne        qw8
  340.         inc        y
  341.         jmp        qw_end
  342. qw8:    cmp        [eax-256],bl
  343.         jne        qw9
  344.         dec        x
  345.         jmp        qw_end
  346. qw9:    cmp        [eax-257],bl
  347.         jne        qw10
  348.         dec        x
  349.         dec        y
  350.         jmp        qw_end
  351. qw10:    cmp        [eax-254],bl
  352.         jne        qw11
  353.         inc        x
  354.         dec        y
  355.         jmp        qw_end
  356. qw11:    cmp        [eax+514],bl
  357.         jne        qw12
  358.         inc        x
  359.         inc        y
  360.         jmp        qw_end
  361. qw12:    cmp        [eax+511],bl
  362.         jne        qw13
  363.         //dec        x
  364.         inc        y
  365.         jmp        qw_end
  366. qw13:    mov        x,255
  367. qw_end:
  368.     };
  369.     *xx=x;
  370.     *yy=y;
  371.     if(x!=255)return true; else return false;
  372. };*/
  373. bool CheckNearRes(byte* xx,byte* yy,byte kind){
  374.     byte x=*xx;
  375.     byte y=*yy;
  376.     if(x==0||y==0)return false;
  377.     __asm{
  378.         xor        eax,eax
  379.         mov        al,x
  380.         mov        ah,y
  381.         mov        bl,kind
  382.         add        eax,offset rtmap
  383.         cmp        [eax-256],bl
  384.         jne        qw1
  385.         dec        y
  386.         jmp        qw_end
  387. qw1:    cmp        [eax-255],bl
  388.         jne        qw2
  389.         dec        y
  390.         jmp        qw_end
  391. qw2:    cmp        [eax+2],bl
  392.         jne        qw3
  393.         inc        x
  394.         jmp        qw_end
  395. qw3:    cmp        [eax+258],bl
  396.         jne        qw4
  397.         inc        x
  398.         jmp        qw_end
  399. qw4:    cmp        [eax-1],bl
  400.         jne        qw5
  401.         dec        x
  402.         jmp        qw_end
  403. qw5://    cmp        [eax+255],bl
  404.     //    jne        qw6
  405.     //    dec        x
  406.     //    jmp        qw_end
  407. qw6:    cmp        [eax+512],bl
  408.         jne        qw7
  409.         inc        y
  410.         jmp        qw_end
  411. qw7:    cmp        [eax+513],bl
  412.         jne        qw8
  413.         inc        y
  414.         jmp        qw_end
  415. qw8://    cmp        [eax-256],bl
  416.     //    jne        qw9
  417.     //    dec        x
  418.     //    jmp        qw_end
  419. qw9://    cmp        [eax-257],bl
  420.     //    jne        qw10
  421.     //    dec        x
  422.     //    dec        y
  423.     //    jmp        qw_end
  424. qw10://    cmp        [eax-254],bl
  425.     //    jne        qw11
  426.     //    inc        x
  427.     //    dec        y
  428.     //    jmp        qw_end
  429. qw11://    cmp        [eax+514],bl
  430.     //    jne        qw12
  431.     //    inc        x
  432.     //    inc        y
  433.     //    jmp        qw_end
  434. qw12://    cmp        [eax+511],bl
  435.     //    jne        qw13
  436.         //dec        x
  437.     //    inc        y
  438.     //    jmp        qw_end
  439. qw13:    mov        x,255
  440. qw_end:
  441.     };
  442.     *xx=x;
  443.     *yy=y;
  444.     if(x!=255)return true; else return false;
  445. };
  446. word OneObject::FindNearestBase(){
  447.     OneObject* OB;
  448.     byte ResID=LocalOrder->info.TakeRes.ResID;
  449.     byte msk=1<<ResID;
  450.     int dist=0xFFFF;
  451.     word OID=0xFFFF;
  452.     for(int i=0;i<MAXOBJECT;i++){
  453.         OB=Group[i];
  454.         if(int(OB)&&(OB->AbRes&msk)&&OB->NNUM==NNUM){
  455.             int dist1=abs(int(x)-int(OB->x))+
  456.                 abs(int(y)-int(OB->y));
  457.             if(dist1<dist){
  458.                 OID=i;
  459.                 dist=dist1;
  460.             };
  461.         };
  462.     };
  463.     return OID;
  464. };
  465. void TakeResLink(OneObject* OBJ);
  466. bool OneObject::TakeResource(byte x,byte y,byte ResID,int Prio){
  467.     if(Prio<PrioryLevel)return false;
  468.     if(!capBuild)return false;
  469.     if(capBuilding)return false;
  470.     //if(RAmount>0&&RType!=ResID)return false;
  471.     RType=ResID;
  472.     RStage=0;
  473.     Order1* Or1=GetOrdBlock();
  474.     if(!int(Or1))return false;
  475.     Or1->PrioryLevel=Prio&127;
  476.     Or1->NextOrder=LocalOrder;
  477.     Or1->OrderType=238;//Take resource
  478.     Or1->OrderTime=0;
  479.     Or1->DoLink=&TakeResLink;
  480.     Or1->info.TakeRes.x=x;
  481.     Or1->info.TakeRes.y=y;
  482.     Or1->info.TakeRes.ResID=ResID;
  483.     Order1* LOR=LocalOrder;
  484.     if(int(InLineCom))FreeAsmLink();
  485.     LocalOrder=Or1;
  486.     //OrderReport=NULL;
  487.     //MessageKind=0;
  488.     //Sender=0xFFFF;
  489.     PrioryLevel=Prio&127;
  490.     return true;
  491. };    
  492. void TakeResLink(OneObject* OBJ){
  493.     assert(!OBJ->AskMade/*TakeResLink*/);
  494.     byte x,y,ResID;
  495.     int dist;
  496.     switch(OBJ->RStage){
  497.         case 0://go to the point and search the resource
  498.             x=OBJ->LocalOrder->info.TakeRes.x;
  499.             y=OBJ->LocalOrder->info.TakeRes.y;
  500.             ResID=OBJ->LocalOrder->info.TakeRes.ResID;
  501.             if(RDS[ResID].Portion<=OBJ->RAmount){
  502.                 OBJ->RStage=1;
  503.                 OBJ->NearBase=OBJ->FindNearestBase();
  504.                 if(OBJ->NearBase==0xFFFF){
  505.                     if(int(OBJ->LocalOrder)){
  506.                         Order1* Or1=OBJ->LocalOrder->NextOrder;
  507.                         OBJ->FreeOrdBlock(OBJ->LocalOrder);
  508.                         OBJ->LocalOrder=Or1;
  509.                         OBJ->Important=false;
  510.                     };
  511.                 };
  512.                 return;
  513.             };
  514.             //ΣαδσΩε δⁿ ∩≤≥ⁿ Σσ≡µΦ∞?
  515.             dist=abs(int(x)-int(OBJ->x))+
  516.                 abs(int(y)-int(OBJ->y));
  517.             if(dist<10){
  518.                 byte xx1=OBJ->x;
  519.                 byte yy1=OBJ->y;
  520.                 if(CheckNearRes(&xx1,&yy1,ResID)){
  521.                     byte dir=drrn[(xx1-OBJ->x+1)*3+yy1-OBJ->y+1];
  522.                     if(dir>7){
  523.                         dir=0;
  524.                     };
  525.                     OBJ->LoadAnimation(0,OBJ->AnmStandKind,0);
  526.                     OBJ->Direction=dir;
  527.                     OBJ->LoadAnimation(2,2,0);
  528.                     OBJ->LoadCurAnm(2);
  529.                     OBJ->isMoving=false;
  530.                     OBJ->RAmount+=TakeResFromCell(xx1,yy1);
  531.                     if(ResID==1){
  532.                         //gold
  533.                         AddWorkEffect(OBJ->x,OBJ->y,OBJ->Ref.General->GoldSound);
  534.                     }else{
  535.                         //wood
  536.                         AddWorkEffect(OBJ->x,OBJ->y,OBJ->Ref.General->TreeSound);
  537.                     };
  538.                     TrMap[OBJ->y][OBJ->x]=1;
  539.                 }else{
  540.                     if(LLock[y][x]){
  541.                         xx1=OBJ->x;
  542.                         yy1=OBJ->y;
  543.                         if(FindResource(&xx1,&yy1,120,ResID,TZones[OBJ->y][OBJ->x])){
  544.                             OBJ->LocalOrder->info.TakeRes.x=xx1;
  545.                             OBJ->LocalOrder->info.TakeRes.y=yy1;
  546.                             OBJ->FreeAsmLink();
  547.                             OBJ->CreateSimplePath(xx1,yy1);
  548.                         };
  549.                     }else if(!int(OBJ->InLineCom)){
  550.                         OBJ->FreeAsmLink();
  551.                         OBJ->CreateSimplePath(x,y);
  552.                     };
  553.                 };
  554.             }else if(!int(OBJ->InLineCom)){
  555.                 OBJ->FreeAsmLink();
  556.                 OBJ->CreateSimplePath(x,y);
  557.             };
  558.             break;
  559.         default:
  560.             if(OBJ->RAmount==0)OBJ->RStage=0;
  561.             if(OBJ->NearBase==0xFFFF){
  562.             OBJ->NearBase=OBJ->FindNearestBase();
  563.                 if(OBJ->NearBase==0xFFFF){
  564.                     if(int(OBJ->LocalOrder)){
  565.                         Order1* Or1=OBJ->LocalOrder->NextOrder;
  566.                         OBJ->FreeOrdBlock(OBJ->LocalOrder);
  567.                         OBJ->LocalOrder=Or1;
  568.                         OBJ->Important=false;
  569.                         return;
  570.                     };
  571.                 };
  572.             };
  573.             word OID=OBJ->NearBase;
  574.             OneObject* OB=Group[OID];
  575.             if(!int(OB)||OB->Sdoxlo){
  576.                 OBJ->NearBase=0xFFFF;
  577.                 return;
  578.             };
  579.             byte x0=OB->x;
  580.             byte y0=OB->y;
  581.             byte olx=OB->Lx;
  582.             byte oly=OB->Ly;
  583.             byte xo=OBJ->x;
  584.             byte yo=OBJ->y;
  585.             if(xo<x0)xo=x0;else if(xo>=x0+olx)xo=x0+olx-1;
  586.             if(yo<y0)yo=y0;else if(yo>=y0+oly)yo=y0+oly-1;
  587.             int sx=xo-OBJ->x;
  588.             int    sy=yo-OBJ->y;
  589.             int dx=abs(sx);
  590.             int dy=abs(sy);
  591.             int dst;
  592.             int rk=OBJ->RType;
  593.                     OBJ->AnmStandKind=RDS[rk].AnmStandKind;
  594.                     OBJ->AnmGoKind=RDS[rk].AnmGoKind;
  595.             if(dx>dy)dst=dx;
  596.                 else dst=dy;
  597.             if(dst<2){
  598.                 int ADDRESRC=int(OBJ->RAmount)*RDS[OBJ->RType].Multi+
  599.                     RESADD[OBJ->NNUM][OBJ->RType];
  600.                 OBJ->Nat->GetTax(OBJ->RType,ADDRESRC);
  601.                 OBJ->RAmount=0;
  602.                 OBJ->RStage=0;
  603.                 OBJ->AnmStandKind=0;
  604.                 OBJ->AnmGoKind=1;
  605.             }else if(!int(OBJ->InLineCom)){
  606.                 OBJ->FreeAsmLink();
  607.                 OBJ->CreateSimplePath(xo,yo);
  608.             };
  609.             
  610.     };
  611. };
  612. word OneObject::FindNearestPort(){
  613.     OneObject* OB;
  614.     GeneralObject* GO;
  615.     int dist=0xFFFF;
  616.     word OID=0xFFFF;
  617.     for(int i=0;i<MAXOBJECT;i++){
  618.         OB=Group[i];
  619.         if(OB)GO=OB->Ref.General;
  620.         if(int(OB)&&GO->OnCost&&OB->NNUM==NNUM){
  621.             int dist1=DistTo(OB->x,OB->y);
  622.             if(dist1<dist){
  623.                 OID=i;
  624.                 dist=dist1;
  625.             };
  626.         };
  627.     };
  628.     return OID;
  629. };
  630. void BuildOnWaterLink(OneObject* OBJ);
  631. bool OneObject::BuildOnWater(word OID,int Prio){
  632.     OneObject* OB=Group[OID];
  633.     if(!int(OB))return false;
  634.     if(!OB->OnWater)return false;
  635.     if(Prio<PrioryLevel)return false;
  636.     if(!capBuild)return false;
  637.     if(capBuilding)return false;
  638.     //if(RAmount>0&&RType!=ResID)return false;
  639.     RStage=0;
  640.     Order1* Or1=GetOrdBlock();
  641.     if(!int(Or1))return false;
  642.     Or1->PrioryLevel=Prio&127;
  643.     Or1->NextOrder=LocalOrder;
  644.     Or1->OrderType=39;//Build on water
  645.     Or1->OrderTime=0;
  646.     Or1->DoLink=&BuildOnWaterLink;
  647.     Or1->info.MoveToObj.ObjIndex=OID;
  648.     Order1* LOR=LocalOrder;
  649.     if(int(InLineCom))FreeAsmLink();
  650.     LocalOrder=Or1;
  651.     //OrderReport=NULL;
  652.     //MessageKind=0;
  653.     //Sender=0xFFFF;
  654.     PrioryLevel=Prio&127;
  655.     return true;
  656. };    
  657. void BuildOnWaterLink(OneObject* OBJ){
  658.     byte x,y,ResID;
  659.     word OI;
  660.     int dist;
  661.     byte xd;
  662.     byte yd;
  663.     word dstx;
  664.     word dst1;
  665.     OneObject* OB;
  666.     switch(OBJ->RStage){
  667.         case 0://go to the object to build
  668.             OI=OBJ->LocalOrder->info.MoveToObj.ObjIndex;
  669.             OB=Group[OI];
  670.             if(OB->Life==OB->MaxLife){
  671.                 Order1* Or1=OBJ->LocalOrder->NextOrder;
  672.                 OBJ->FreeOrdBlock(OBJ->LocalOrder);
  673.                 OBJ->LocalOrder=Or1;
  674.                 OBJ->Important=false;
  675.                 if(OI==OBJ->Nat->OilBaseID){
  676.                     OBJ->GetOil(OI,16);
  677.                 };
  678.                 return;
  679.             };
  680.             x=OB->x+1;
  681.             y=OB->y+1;
  682.             xd=x;
  683.             yd=y;
  684.             dstx=1000;
  685.             if(!WLock[y-2][x]){
  686.                 dst1=OBJ->DistTo(x,y-2);
  687.                 if(dst1<dstx){
  688.                     dstx=dst1;
  689.                     xd=x;
  690.                     yd=y-2;
  691.                 };
  692.             };
  693.             if(!WLock[y+2][x]){
  694.                 dst1=OBJ->DistTo(x,y+2);
  695.                 if(dst1<dstx){
  696.                     dstx=dst1;
  697.                     xd=x;
  698.                     yd=y+2;
  699.                 };
  700.             };
  701.             if(!WLock[y][x-2]){
  702.                 dst1=OBJ->DistTo(x-2,y);
  703.                 if(dst1<dstx){
  704.                     dstx=dst1;
  705.                     xd=x-2;
  706.                     yd=y;
  707.                 };
  708.             };
  709.             if(!WLock[y][x+2]){
  710.                 dst1=OBJ->DistTo(x+2,y);
  711.                 if(dst1<dstx){
  712.                     dstx=dst1;
  713.                     xd=x+2;
  714.                     yd=y;
  715.                 };
  716.             };
  717.             if(OBJ->DistTo(x,y)<=2){
  718.                 OB->NextStage();
  719.                 OB->NextStage();
  720.                 if(OB->Life==OB->MaxLife){
  721.                     Order1* Or1=OBJ->LocalOrder->NextOrder;
  722.                     OBJ->FreeOrdBlock(OBJ->LocalOrder);
  723.                     OBJ->LocalOrder=Or1;
  724.                     OBJ->Important=false;
  725.                     return;
  726.                 };
  727.                 OBJ->RStage=1;
  728.                 OBJ->FindNearestPort();
  729.                 return;
  730.             };
  731.             OBJ->FreeAsmLink();
  732.             OBJ->CreateWPath(xd,yd);
  733.             break;
  734.         default:
  735.             if(OBJ->NearBase==0xFFFF)
  736.                 OBJ->NearBase=OBJ->FindNearestPort();
  737.             if(OBJ->NearBase==0xFFFF){
  738.                 if(int(OBJ->LocalOrder)){
  739.                     Order1* Or1=OBJ->LocalOrder->NextOrder;
  740.                     OBJ->FreeOrdBlock(OBJ->LocalOrder);
  741.                     OBJ->LocalOrder=Or1;
  742.                     OBJ->Important=false;
  743.                     return;
  744.                 };
  745.             };
  746.             word OID=OBJ->NearBase;
  747.             OneObject* OB=Group[OID];
  748.             if(!int(OB)||OB->Sdoxlo||!OB->capBase){
  749.                 OBJ->NearBase=0xFFFF;
  750.                 return;
  751.             };
  752.             x=(OB->x+1)&254;
  753.             y=(OB->y+1)&254;
  754.             xd=x;
  755.             yd=y;
  756.             dstx=1000;
  757.             if(!WLock[y-2][x]){
  758.                 dst1=OBJ->DistTo(x,y-2);
  759.                 if(dst1<dstx){
  760.                     dstx=dst1;
  761.                     xd=x;
  762.                     yd=y-2;
  763.                 };
  764.             };
  765.             if(!WLock[y+2][x]){
  766.                 dst1=OBJ->DistTo(x,y+2);
  767.                 if(dst1<dstx){
  768.                     dstx=dst1;
  769.                     xd=x;
  770.                     yd=y+2;
  771.                 };
  772.             };
  773.             if(!WLock[y][x-2]){
  774.                 dst1=OBJ->DistTo(x-2,y);
  775.                 if(dst1<dstx){
  776.                     dstx=dst1;
  777.                     xd=x-2;
  778.                     yd=y;
  779.                 };
  780.             };
  781.             if(!WLock[y][x+2]){
  782.                 dst1=OBJ->DistTo(x+2,y);
  783.                 if(dst1<dstx){
  784.                     dstx=dst1;
  785.                     xd=x+2;
  786.                     yd=y;
  787.                 };
  788.             };
  789.             byte x0=OB->x+1;
  790.             byte y0=OB->y+1;
  791.             OBJ->AnmStandKind=0;
  792.             OBJ->AnmGoKind=1;
  793.             if(OBJ->DistTo(x0,y0)<=3)
  794.                 OBJ->RStage=0;
  795.             else OBJ->CreateWPath(xd,yd);
  796.     };
  797. };
  798. void GetOilLink(OneObject* OBJ);
  799. bool OneObject::GetOil(word OID,int Prio){
  800.     OneObject* OB=Group[OID];
  801.     if(!int(OB))return false;
  802.     if(!OB->OnWater)return false;
  803.     if(Prio<PrioryLevel)return false;
  804.     if(!capBuild)return false;
  805.     if(capBuilding)return false;
  806.     //if(RAmount>0&&RType!=ResID)return false;
  807.     RStage=0;
  808.     Order1* Or1=GetOrdBlock();
  809.     if(!int(Or1))return false;
  810.     Or1->PrioryLevel=Prio&127;
  811.     Or1->NextOrder=LocalOrder;
  812.     Or1->OrderType=39;//Build on water
  813.     Or1->OrderTime=0;
  814.     Or1->DoLink=&GetOilLink;
  815.     Or1->info.MoveToObj.ObjIndex=OID;
  816.     Order1* LOR=LocalOrder;
  817.     if(int(InLineCom))FreeAsmLink();
  818.     LocalOrder=Or1;
  819.     //OrderReport=NULL;
  820.     //MessageKind=0;
  821.     //Sender=0xFFFF;
  822.     PrioryLevel=Prio&127;
  823.     return true;
  824. };    
  825. void GetOilLink(OneObject* OBJ){
  826.     byte x,y,ResID;
  827.     word OI;
  828.     int dist;
  829.     byte xd,x0,y0,x1,y1,xx,yy;
  830.     byte yd;
  831.     word dstx;
  832.     int uu=32;
  833.     word dst1;
  834.     OneObject* OB;
  835.     switch(OBJ->RStage){
  836.         case 0://go to the object to build
  837.             OI=OBJ->LocalOrder->info.MoveToObj.ObjIndex;
  838.             OB=Group[OI];
  839.             //if(OB->Life==OB->MaxLife){
  840.             //    Order1* Or1=OBJ->LocalOrder->NextOrder;
  841.             //    OBJ->FreeOrdBlock(OBJ->LocalOrder);
  842.             //    OBJ->LocalOrder=Or1;
  843.             //    OBJ->Important=false;
  844.             //    return;
  845.             //};
  846.             x=OB->x+1;
  847.             y=OB->y+1;
  848.             xd=x;
  849.             yd=y;
  850.             dstx=1000;
  851.             if(!WLock[y-2][x]){
  852.                 dst1=OBJ->DistTo(x,y-2);
  853.                 if(dst1<dstx){
  854.                     dstx=dst1;
  855.                     xd=x;
  856.                     yd=y-2;
  857.                 };
  858.             };
  859.             if(!WLock[y+2][x]){
  860.                 dst1=OBJ->DistTo(x,y+2);
  861.                 if(dst1<dstx){
  862.                     dstx=dst1;
  863.                     xd=x;
  864.                     yd=y+2;
  865.                 };
  866.             };
  867.             if(!WLock[y][x-2]){
  868.                 dst1=OBJ->DistTo(x-2,y);
  869.                 if(dst1<dstx){
  870.                     dstx=dst1;
  871.                     xd=x-2;
  872.                     yd=y;
  873.                 };
  874.             };
  875.             if(!WLock[y][x+2]){
  876.                 dst1=OBJ->DistTo(x+2,y);
  877.                 if(dst1<dstx){
  878.                     dstx=dst1;
  879.                     xd=x+2;
  880.                     yd=y;
  881.                 };
  882.             };
  883.             if(OBJ->DistTo(x,y)<=2&&OB->Ready){
  884.                 OB->AnmStandKind=4;
  885.                 OB->LoadAnimation(0,4,0);
  886.                 OB->LoadCurAnm(0);
  887.                 Mops[OBJ->y][OBJ->x]=0xFFFF;
  888.                 WLock[OBJ->y][OBJ->x]=0;
  889.                 WMap[OBJ->y][OBJ->x]=0;
  890.                 OBJ->x=OB->x;
  891.                 OBJ->y=OB->y;
  892.                 OB->Ready=false;
  893.                 OB->Wait=100;
  894.                 OBJ->RStage=2;
  895.                 return;
  896.             };
  897.             OBJ->FreeAsmLink();
  898.             OBJ->CreateWPath(xd,yd);
  899.             break;
  900.         case 2:
  901.             OI=OBJ->LocalOrder->info.MoveToObj.ObjIndex;
  902.             OB=Group[OI];
  903.             if(OB->Life==0){
  904.                 Order1* Or1=OBJ->LocalOrder->NextOrder;
  905.                 OBJ->FreeOrdBlock(OBJ->LocalOrder);
  906.                 OBJ->LocalOrder=Or1;
  907.                 OBJ->Important=false;
  908.                 OBJ->Die();
  909.                 return;
  910.             };
  911.             if(OB->Wait){
  912.                 OB->Wait--;
  913.                 return;
  914.             };
  915.             x0=((OB->x+1)&254)-2;
  916.             y0=((OB->y+1)&254)-2;
  917.             x1=(x0+4);
  918.             y1=(y0+4);
  919.             do{
  920.                 xx=x0;
  921.                 for(yy=y0;yy<=y1;yy+=2)
  922.                     if(!WLock[yy][xx])goto zzz;
  923.                 xx=x1;
  924.                 for(yy=y0;yy<=y1;yy+=2)
  925.                     if(!WLock[yy][xx])goto zzz;
  926.                 yy=y0;
  927.                 for(xx=x0+2;xx<x1;xx+=2)
  928.                     if(!WLock[yy][xx])goto zzz;
  929.                 yy=y1;
  930.                 for(xx=x0+2;xx<x1;xx+=2)
  931.                     if(!WLock[yy][xx])goto zzz;
  932.                 if(x0>2)x0-=2;
  933.                 if(y0>2)y0-=2;
  934.                 if(x1<msx-2)x1+=2;
  935.                 if(y1<msy-2)y1+=2;
  936.                 uu--;
  937.             }while(uu);
  938. zzz:
  939.             OB->Ready=true;
  940.             OB->AnmStandKind=0;
  941.             OB->LoadAnimation(0,0,0);
  942.             OB->LoadCurAnm(0);
  943.             OBJ->x=xx;
  944.             OBJ->y=yy;
  945.             Mops[yy][xx]=OBJ->Index;
  946.             WLock[yy][xx]=1;
  947.             OBJ->NearBase=OBJ->FindNearestPort();
  948.             OBJ->RStage=1;
  949.             break;
  950.         default:
  951.             if(OBJ->NearBase==0xFFFF)
  952.                 OBJ->NearBase=OBJ->FindNearestPort();
  953.             if(OBJ->NearBase==0xFFFF){
  954.                 if(int(OBJ->LocalOrder)){
  955.                     Order1* Or1=OBJ->LocalOrder->NextOrder;
  956.                     OBJ->FreeOrdBlock(OBJ->LocalOrder);
  957.                     OBJ->LocalOrder=Or1;
  958.                     OBJ->Important=false;
  959.                     return;
  960.                 };
  961.             };
  962.             word OID=OBJ->NearBase;
  963.             OneObject* OB=Group[OID];
  964.             if(!int(OB)||OB->Sdoxlo){
  965.                 OBJ->NearBase=0xFFFF;
  966.                 return;
  967.             };
  968.             x=(OB->x+1)&254;
  969.             y=(OB->y+1)&254;
  970.             xd=x;
  971.             yd=y;
  972.             dstx=1000;
  973.             if(!WLock[y-2][x]){
  974.                 dst1=OBJ->DistTo(x,y-2);
  975.                 if(dst1<dstx){
  976.                     dstx=dst1;
  977.                     xd=x;
  978.                     yd=y-2;
  979.                 };
  980.             };
  981.             if(!WLock[y+2][x]){
  982.                 dst1=OBJ->DistTo(x,y+2);
  983.                 if(dst1<dstx){
  984.                     dstx=dst1;
  985.                     xd=x;
  986.                     yd=y+2;
  987.                 };
  988.             };
  989.             if(!WLock[y][x-2]){
  990.                 dst1=OBJ->DistTo(x-2,y);
  991.                 if(dst1<dstx){
  992.                     dstx=dst1;
  993.                     xd=x-2;
  994.                     yd=y;
  995.                 };
  996.             };
  997.             if(!WLock[y][x+2]){
  998.                 dst1=OBJ->DistTo(x+2,y);
  999.                 if(dst1<dstx){
  1000.                     dstx=dst1;
  1001.                     xd=x+2;
  1002.                     yd=y;
  1003.                 };
  1004.             };
  1005.             byte x0=OB->x+1;
  1006.             byte y0=OB->y+1;
  1007.             OBJ->AnmStandKind=0;
  1008.             OBJ->AnmGoKind=1;
  1009.             if(OBJ->DistTo(x0,y0)<=3){
  1010.                 OBJ->RStage=0;
  1011.                 RESRC[OBJ->NNUM][3]+=10;
  1012.             }else OBJ->CreateWPath(xd,yd);
  1013.     };
  1014. };
  1015. extern int RealLx;
  1016. void ShowRMap(){
  1017.     //int x=smapx+smaplx*32-140;
  1018.     int x=RealLx-200;
  1019.     //if(MiniMode)x=RealLx-200;//smapx+(smaplx<<4)-140;
  1020.     int y=smapy;
  1021.     char gg[100];
  1022.     for(int i=0;i<3;i++){
  1023.         if(RDS[i].Enabled){
  1024.             sprintf(gg,"%s : %d",RDS[i].Name,RESRC[MyNation][i]);
  1025.             ShowString(x,y,gg,&rlf_s);
  1026.             y+=16;
  1027.         };
  1028.     };
  1029.     //sprintf(gg,"Cash: %d",NATIONS[MyNation].CasheSize);
  1030.     //ShowString(x,y,gg,&rlf_s);
  1031.     //y+=16;
  1032.     return;
  1033.     char ggg[32];
  1034.     for(i=0;i<smaplx;i++)
  1035.         for(int j=0;j<smaply;j++){
  1036.             byte res=CMap[j+mapy-1][i+mapx-1];
  1037.             if(res!=255){
  1038.                 sprintf(ggg,"%d",RZAMap[j+mapy][i+mapx]);//[res);
  1039.                 ShowString(smapx+32*i-8+16,smapy+32*j-8+16,ggg,&rlf_s);
  1040.                 //Hline(smapx+32*i-3,smapy+32*j,smapx+32*i+3,res);
  1041.                 //Vline(smapx+32*i,smapy+32*j-3,smapy+32*j+3,res);
  1042.             };
  1043.         };
  1044. };
  1045. bool CheckCost(byte NI,byte ResID,word Amount){
  1046.         if(ResID==255)return true;
  1047.         if(RESRC[NI][ResID]>=Amount)return true;
  1048.         else return false;
  1049. };
  1050. bool CheckOilSpot(byte x,byte y){
  1051.     if(x>2&&x<msx-2&&y>2&&y<msy-2){
  1052.         if(!(WLock[y][x]||WLock[y+1][x]||WLock[y][x+1]||
  1053.             WLock[y-1][x]||WLock[y][x+1]||OILMAP[y>>1][x>>1]))
  1054.             return true;
  1055.     };
  1056.     return false;
  1057. };
  1058. void CreateOilSpot(byte x,byte y){
  1059.     OILMAP[y>>1][x>>1]=60000;
  1060. };
  1061. void ShowOilSpot(int x,int y){
  1062.     ShowRLCItem(x+OILOC.dx,y+OILOC.dy,&MImage[OILOC.FileID],OILOC.spr,0);
  1063. };
  1064. void CreateOilSpotAnyway(){
  1065.     for(int i=0;i<500;i++){
  1066.         byte x=rando()&255;
  1067.         byte y=rando()&255;
  1068.         if(CheckOilSpot(x,y)){
  1069.             CreateOilSpot(x,y);
  1070.             return;
  1071.         };
  1072.     };
  1073. };
  1074. void ShowResScreen(){
  1075.     for(int i=0;i<smaplx;i++)
  1076.         for(int j=0;j<smaply;j++){
  1077.             byte x=i+mapx;
  1078.             byte y=j+mapy;
  1079.             if(!((x&1)||(y&1))){
  1080.                 if(OILMAP[y>>1][x>>1]){
  1081.                     ShowOilSpot(smapx+(i<<5)-32,smapy+(j<<5)-32);
  1082.                 };
  1083.             };
  1084.         };
  1085. };
  1086.