home *** CD-ROM | disk | FTP | other *** search
/ WarCraft 2000 - Nuclear Epidemic / W2000.nrg / SOURCE.War2000 / Build.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-18  |  12.0 KB  |  498 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 "Nature.h"
  9. #include "Megapolis.h"
  10. #include "GSound.h"
  11. bool CheapMode;
  12. void PerformAction(OneObject* OB,int x,int y);
  13. extern const int drr[9]={7,6,5,0,0,4,1,2,3};
  14. extern word LastObject;
  15. void AssignHint1(char* s,int time);
  16. bool Nation::CheckBuilding(word ID,byte x,byte y){
  17.     if(!Mon[ID]->cpbBuilding)return false;
  18.     int    sx=Mon[ID]->SizeX;
  19.     if(Mon[ID]->OnCost){
  20.         int IsCost=false;
  21.         for(int dx=0;dx<sx;dx++)
  22.             for(int dy=0;dy<sx;dy++){
  23.                 int ti=tmap[x+dx-1][y+dy-1];
  24.                 if(ti<29||ti>50)ti=0;
  25.                 if(ti)IsCost++;
  26.                 if((Mops[y+dy][x+dx]!=0xFFFF)||(WLock[y+dy][x+dx]&&!ti))return false;
  27.             };
  28.             if(IsCost<3)return false;else return true;
  29.     }else
  30.         if(Mon[ID]->OnOil){
  31.             byte xp=x+1;
  32.             byte yp=y+1;
  33.             if((xp&1)||(yp&1))return false;
  34.             if(OILMAP[yp>>1][xp>>1]&&!WLock[yp][xp])
  35.                 return true;
  36.             return false;
  37.         }else
  38.             for(int dx=0;dx<sx;dx++)
  39.                 for(int dy=0;dy<sx;dy++)
  40.                     if(LLock[y+dy][x+dx])return false;
  41.     return true;
  42. };
  43. int Nation::CreateBuilding(word ID,byte x,byte y){
  44.     GeneralObject* GO=Mon[ID];
  45.     byte NIN=NNUM;
  46.     if(!CheapMode){
  47.         if(!CheckCost(NIN,GO->ResourceID[0],GO->ResAmount[0]))return -1;
  48.         if(!CheckCost(NIN,GO->ResourceID[1],GO->ResAmount[1]))return -1;
  49.         if(!CheckCost(NIN,GO->ResourceID[2],GO->ResAmount[2]))return -1;
  50.         if(!CheckCost(NIN,GO->ResourceID[3],GO->ResAmount[3]))return -1;
  51.         if(GO->ResourceID[0]!=255)RESRC[NNUM][GO->ResourceID[0]]-=GO->ResAmount[0];
  52.         if(GO->ResourceID[1]!=255)RESRC[NNUM][GO->ResourceID[1]]-=GO->ResAmount[1];
  53.         if(GO->ResourceID[2]!=255)RESRC[NNUM][GO->ResourceID[2]]-=GO->ResAmount[2];
  54.         if(GO->ResourceID[3]!=255)RESRC[NNUM][GO->ResourceID[3]]-=GO->ResAmount[3];
  55.     };
  56.     if(!CheckBuilding(ID,x,y))return -1;
  57.     byte sx=Mon[ID]->SizeX;
  58.     for(int i=0;i<MaxObj&&int(Group[i]);i++);
  59.     if(i>MaxObj)return -1;
  60.     if(ID>=NMon) return -1;
  61.     Group[i]=new OneObject;
  62.     OneObject* G=Group[i];
  63.     if(i>=MAXOBJECT)MAXOBJECT=i+1;
  64.     //if(GO->cpbFarm)NFarms++;
  65.     G->DefaultSettings(GO);
  66.     G->Teleport=false;
  67.     G->capTeleport=GO->Teleport;
  68.     G->NNUM=NNUM;
  69.     G->Media=0;
  70.     G->CrowdRef=NULL;
  71.     G->Kind=GO->Kind;
  72.     Cell8x8* CELL=&TCInf[NNUM][y>>2][x>>2];
  73.     CELL->UnitsAmount[GO->Kind]++;
  74.     G->VisRadius=GO->VisRadius;
  75.     G->VisSpots=GO->VisSpots;
  76.     G->SpotType=GO->SpotType;
  77.     G->SpotSize=GO->SpotSize;
  78.     G->OnWater=GO->OnWater;
  79.     G->DangerZone=GO->DangerZone;
  80.     G->NoSearchVictim=GO->NoSearchVictim;
  81.     G->NoAnswer=GO->NoAnswer;
  82.     G->NeedNoHelp=GO->NeedNoHelp;
  83.     G->Nat=this;
  84.     G->Ready=false;
  85.     G->wepX=GO->wepX;
  86.     G->wepY=GO->wepY;
  87.     G->MaxDelay=GO->delay;
  88.     G->delay=0;
  89.     G->Lx=GO->SizeX;
  90.     G->Ly=GO->SizeY;
  91.     G->NIndex=ID;
  92.     G->GroupIndex=NULL;
  93.     G->TempFlag=false;
  94.     G->Mobilised=false;
  95.     G->Wars=NULL;
  96.     G->Index=i;
  97.     Visuals* m;
  98.     m=(Visuals*)Mon[ID];
  99.     G->Selected=false;
  100.     G->Borg=false;
  101.     G->Life=2;
  102.     G->MaxLife=m->info.Basic.MaxLife;
  103.     G->Ref.Visual=m;
  104.     G->x=x;
  105.     G->y=y;
  106.     G->Push=false;
  107.     G->Direction=0;
  108.     memset(&(G->ARegs),0,sizeof G->ARegs);
  109.     G->LoadAnimation(0,6,0);
  110.     G->LoadCurAnm(0);
  111.     G->LocalOrder=NULL;
  112.     //G->OrderReport=NULL;
  113.     //G->MessageFlags=0;
  114.     G->PrioryLevel=0;
  115.     //G->MessageKind=0;
  116.     G->InLineCom=NULL;
  117.     G->LineOffset=0;
  118.     G->Ticks=0;
  119.     G->TicksPerChange=255;
  120.     G->Wait=0;
  121.     G->Addx=0;
  122.     G->Addy=0;
  123.     G->Npush=0;
  124.     G->StandTime=100;
  125.     G->Sdoxlo=false;
  126.     G->Weap=Mon[ID]->Weap;
  127.     G->NMask=NMask;
  128.     G->Important=false;
  129.     G->EnemyDist=5000;
  130.     G->Attack=false;
  131.     G->EnemyID=0xFFFF;
  132.     G->Egoist=false;
  133.     G->NStages=GO->NStages;
  134.     G->Stage=0;
  135.     G->NextStage();
  136.     G->capBuilding=true;
  137.     G->AnmGoKind=1;
  138.     G->AnmStandKind=0;
  139.     for(byte dx=0;dx<sx;dx++)
  140.         for(byte dy=0;dy<sx;dy++){
  141.             LLock[y+dy][x+dx]=1;
  142.             IncLock(x+dx,y+dy);
  143.             TrMap[y+dy][x+dx]=1;
  144.             WMap[y+dy][x+dx]=1;
  145.             WLock[y+dy][x+dx]=1;
  146.             Mops[y+dy][x+dx]=i;
  147.         };
  148.     return i;
  149. };
  150. void OneObject::NextStage(){
  151.     if(!capBuilding||Life==MaxLife)return;
  152.     if(Stage<NStages){
  153.         Stage++;
  154.         LoadCurAnm(0);
  155.         TicksPerChange=255;
  156.         Life=div(Stage*MaxLife,NStages).quot;
  157.         CurrentSprite=div(Stage*(CurAnm->count-1),NStages).quot;
  158.         if(Stage==NStages){
  159.             if((!Ready)&&Ref.General->cpbFarm)Nat->NFarms++;
  160.             Ready=true;
  161.         };
  162.     }else{
  163.         Life+=20;
  164.         LoadCurAnm(0);
  165.         TicksPerChange=255;
  166.         if(Life>MaxLife)Life=MaxLife;
  167.         CurrentSprite=CurAnm->count-1;
  168.         Ready=true;
  169.     };
  170. };
  171. void BuildObjLink(OneObject* OBJ);
  172. bool OneObject::BuildObj(word OID,int Prio){
  173.     if(OnWater){
  174.         return BuildOnWater(OID,Prio);
  175.     };
  176.     if(Prio<PrioryLevel&&Prio<100)return false;
  177.     if(!capBuild)return false;
  178.     if(capBuilding)return false;
  179.     OneObject* OB=Group[OID];
  180.     if(!int(OB)||OB->Sdoxlo)return false;
  181.     if(!OB->capBuilding)return false ;
  182.     if(!(OB->NMask&NMask))return false;
  183.     if(OB->Life==MaxLife)return false;
  184.     byte x1=OB->x;
  185.     byte y1=OB->y;
  186.     int sx=x1-x;
  187.     int    sy=y1-y;
  188.     int dx=abs(sx);
  189.     int dy=abs(sy);
  190.     int dst;
  191.     if(dx>dy)dst=dx;
  192.             else dst=dy;
  193.     Important=true;
  194.     Order1* Or1=GetOrdBlock();
  195.     if(!int(Or1))return false;
  196.     Or1->PrioryLevel=Prio&127;
  197.     Or1->NextOrder=LocalOrder;
  198.     Or1->OrderType=89;//Build
  199.     Or1->OrderTime=0;
  200.     Or1->DoLink=&BuildObjLink;
  201.     Or1->info.MoveToObj.ObjIndex=OID;
  202.     Order1* LOR=LocalOrder;
  203.     if(int(InLineCom))FreeAsmLink();
  204.     LocalOrder=Or1;
  205.     //OrderReport=NULL;
  206.     //MessageKind=0;
  207.     //Sender=0xFFFF;
  208.     PrioryLevel=Prio&127;
  209.     return true;
  210. };    
  211. void BuildObjLink(OneObject* OBJ){
  212.     word OID=OBJ->LocalOrder->info.MoveToObj.ObjIndex;
  213.     OneObject* OB=Group[OID];
  214.     //byte NI=OBJ->NNUM;
  215.     //if(OB->cost>RESRC[NI][1])return;
  216.     OBJ->Important=true;
  217.     Order1* Or1;
  218.     if((!int(OB))||OB->Sdoxlo||OB->Life==OB->MaxLife){
  219.         if(int(OBJ->InLineCom))OBJ->FreeAsmLink();
  220.         if(int(OBJ->LocalOrder)){
  221.         //    RESRC[NI][1]-=OB->cost;
  222.             Or1=OBJ->LocalOrder->NextOrder;
  223.             OBJ->FreeOrdBlock(OBJ->LocalOrder);
  224.             OBJ->LocalOrder=Or1;
  225.             OBJ->Important=false;
  226.             return;
  227.         };
  228.     };
  229.     TrMap[OBJ->y][OBJ->x]=0;
  230.     byte x0=OB->x;
  231.     byte y0=OB->y;
  232.     byte olx=OB->Lx;
  233.     byte oly=OB->Ly;
  234.     byte xo=OBJ->x;
  235.     byte yo=OBJ->y;
  236.     if(xo<x0)xo=x0;else if(xo>=x0+olx)xo=x0+olx-1;
  237.     if(yo<y0)yo=y0;else if(yo>=y0+oly)yo=y0+oly-1;
  238.     int sx=xo-OBJ->x;
  239.     int    sy=yo-OBJ->y;
  240.     int dx=abs(sx);
  241.     int dy=abs(sy);
  242.     int dst;
  243.     if(dx>dy)dst=dx;
  244.             else dst=dy;
  245.     if(dst<2){
  246.         OBJ->Direction=drr[(sx+1)*3+sy+1];
  247.         OBJ->LoadAnimation(2,2,0);
  248.         AddWorkEffect(OBJ->x,OBJ->y,OBJ->Ref.General->TreeSound);
  249.         OBJ->LoadCurAnm(2);
  250.         OB->NextStage();
  251.         TrMap[OBJ->y][OBJ->x]=1;
  252.         OBJ->isMoving=false;
  253.     }else{
  254.         byte x0=OB->x-1;
  255.         byte y0=OB->y-1;
  256.         byte olx=OB->Lx+2;
  257.         byte oly=OB->Ly+2;
  258.         byte xo=OBJ->x;
  259.         byte yo=OBJ->y;
  260.         if(xo<x0)xo=x0;else if(xo>=x0+olx)xo=x0+olx-1;
  261.         if(yo<y0)yo=y0;else if(yo>=y0+oly)yo=y0+oly-1;
  262.         if(TrMap[yo][xo]){//search for nearest empty point
  263.             int dst=1000; 
  264.             int dst1;
  265.             olx--;
  266.             oly--;
  267.             for(byte pp=0;pp<olx;pp++){
  268.                 if(!TrMap[y0+pp][x0]){
  269.                     dst1=OBJ->DistTo(x0,y0+pp);
  270.                     if(dst1<dst){
  271.                         xo=x0;
  272.                         yo=y0+pp;
  273.                         dst=dst1;
  274.                     };
  275.                 };
  276.             };
  277.             for(pp=0;pp<olx;pp++){
  278.                 if(!TrMap[y0+pp+1][x0+olx]){
  279.                     dst1=OBJ->DistTo(x0+olx,y0+pp+1);
  280.                     if(dst1<dst){
  281.                         xo=x0+olx;
  282.                         yo=y0+pp+1;
  283.                         dst=dst1;
  284.                     };
  285.                 };
  286.             };
  287.             for(pp=0;pp<olx;pp++){
  288.                 if(!TrMap[y0+olx][x0+pp]){
  289.                     dst1=OBJ->DistTo(x0+pp,y0+olx);
  290.                     if(dst1<dst){
  291.                         xo=x0+pp;
  292.                         yo=y0+olx;
  293.                         dst=dst1;
  294.                     };
  295.                 };
  296.             };
  297.             for(pp=0;pp<olx;pp++){
  298.                 if(!TrMap[y0][x0+pp+1]){
  299.                     dst1=OBJ->DistTo(x0+pp+1,y0);
  300.                     if(dst1<dst){
  301.                         xo=x0+pp+1;
  302.                         yo=y0;
  303.                         dst=dst1;
  304.                     };
  305.                 };
  306.             };
  307.         };
  308.         OBJ->FreeAsmLink();
  309.         OBJ->CreatePath(xo,yo);
  310.     };
  311. };
  312. //return 0-unable
  313. //       n-busy(n=number of tasks)
  314. //         -1-ready
  315. int OneObject::CheckAbility(word ID){
  316.     if(!capBuilding)return 0;
  317.     Nation* NT=Nat;
  318.     word NInd=NIndex;
  319.     int p=NT->PACount[NInd];
  320.     for(int i=0;i<p;i++){
  321.         if(NT->PAble[NInd][i]==ID)break;
  322.     };
  323.     if(i>=p)return 0;
  324.     int j=0;
  325.     Order1* Ord1=LocalOrder;
  326.     while(int(Ord1)){
  327.         if(Ord1->OrderType==13)j++;
  328.         Ord1=Ord1->NextOrder;
  329.     };
  330.     if(j==0)return -1;
  331.     return j;    
  332. };
  333. void ProduceObjLink(OneObject* OBJ);
  334. void OneObject::Produce(word ID){
  335.     if(!(capBuilding&&Ready))return;
  336.     if(int(Nat->NFarms)*15<Nat->NGidot+1){
  337.         if(NNUM==MyNation){
  338.             AssignHint1("═σΣε±≥α≥ε≈φε ⌠σ≡∞.",30);
  339.         };
  340.         return;
  341.     };
  342.     byte NI=Nat->NNUM;
  343.     int xcost=Nat->Mon[ID]->cost;
  344.     if(RESRC[NI][1]<xcost){
  345.         AssignHint1("═σΣε±≥α≥ε≈φε τεδε≥α.",30);
  346.         return;
  347.     };
  348.     RESRC[NI][1]-=xcost;
  349.     Order1* Or1=GetOrdBlock();
  350.     Or1->PrioryLevel=0;
  351.     Or1->NextOrder=LocalOrder;
  352.     Or1->OrderType=13;//Produce
  353.     Or1->OrderTime=0;
  354.     Or1->DoLink=&ProduceObjLink;
  355.     Or1->info.Produce.ObjIndex=ID;
  356.     Order1* LOR=LocalOrder;
  357.     if(int(InLineCom))FreeAsmLink();
  358.     LocalOrder=Or1;
  359.     LocalOrder->info.Produce.PStep=1;
  360.     LocalOrder->info.Produce.Progress=0;
  361.     LocalOrder->info.Produce.NStages=Nat->Mon[ID]->NStages<<1;
  362.     //OrderReport=NULL;
  363.     //MessageKind=0;
  364.     //Sender=0xFFFF;
  365. };    
  366. void ProduceObjLink(OneObject* OBJ){
  367.     word OI=OBJ->LocalOrder->info.Produce.ObjIndex;
  368.     Nation* NT=OBJ->Nat;
  369.     if(int(NT->NFarms)*15<NT->NGidot+1){
  370.         if(NT->NNUM==MyNation){
  371.             sprintf(Prompt,"═σΣε±≥α≥ε≈φε ⌠σ≡∞.");
  372.             PromptTime=100;
  373.         };
  374.         return;
  375.     };
  376.     byte NI=NT->NNUM;
  377.     int xcost=NT->Mon[OI]->cost;
  378.     //if(RESRC[NI][1]<xcost)return;
  379.     byte step=OBJ->LocalOrder->info.Produce.PStep;
  380.     word xxx=OBJ->LocalOrder->info.Produce.Progress;
  381.     word nxxx=OBJ->LocalOrder->info.Produce.NStages;
  382. //    byte NI=OBJ->NNUM;
  383. //    if(OB->cost>RESRC[NI][1])return;
  384.     xxx+=step;
  385.     OBJ->LocalOrder->info.Produce.Progress=xxx;
  386.     if(xxx<nxxx)return;
  387.     //search for place   
  388.     byte x0=OBJ->x-1;
  389.     byte y0=OBJ->y-1;
  390.     byte x1=OBJ->x+OBJ->Lx;
  391.     byte y1=OBJ->y+OBJ->Ly;
  392.     byte yy,xx;
  393.     GeneralObject* GO=NT->Mon[OI];
  394.     if(GO->OnWater){
  395.         x0&=254;
  396.         y0&=254;
  397.         x1=(x1+1)&254;
  398.         y1=(y1+1)&254;
  399.         int uu=32;
  400.         do{
  401.             xx=x0;
  402.             for(yy=y0;yy<=y1;yy+=2)
  403.                 if(!WLock[yy][xx])goto zzz;
  404.             xx=x1;
  405.             for(yy=y0;yy<=y1;yy+=2)
  406.                 if(!WLock[yy][xx])goto zzz;
  407.             yy=y0;
  408.             for(xx=x0+2;xx<x1;xx+=2)
  409.                 if(!WLock[yy][xx])goto zzz;
  410.             yy=y1;
  411.             for(xx=x0+2;xx<x1;xx+=2)
  412.                 if(!WLock[yy][xx])goto zzz;
  413.             if(x0>2)x0-=2;
  414.             if(y0>2)y0-=2;
  415.             if(x1<msx-2)x1+=2;
  416.             if(y1<msy-2)y1+=2;
  417.             uu--;
  418.         }while(uu);
  419.     }else{
  420.         do{
  421.             xx=x0;
  422.             for(yy=y0;yy<=y1;yy++)
  423.                 if(!LLock[yy][xx])goto zzz;
  424.             xx=x1;
  425.             for(yy=y0;yy<=y1;yy++)
  426.                 if(!LLock[yy][xx])goto zzz;
  427.             yy=y0;
  428.             for(xx=x0+1;xx<x1;xx++)
  429.                 if(!LLock[yy][xx])goto zzz;
  430.             yy=y1;
  431.             for(xx=x0+1;xx<x1;xx++)
  432.                 if(!LLock[yy][xx])goto zzz;
  433.             if(x0>1)x0--;
  434.             if(y0>1)y0--;
  435.             if(x1<msx)x1++;
  436.             if(y1<msy)y1++;
  437.         }while(true);
  438.     };
  439. zzz:
  440.     if(GO->OnWater){
  441.         if(!WLock[yy][xx]){
  442.             //RESRC[NI][1]-=xcost;
  443.             OBJ->Nat->CreateTerrainAt(xx,yy,OBJ->LocalOrder->info.Produce.ObjIndex);
  444.             if(OBJ->DstX&&LastObject!=0xFFFF)PerformAction(Group[LastObject],OBJ->DstX,OBJ->DstY);
  445.         };
  446.     }else
  447.     if(!LLock[yy][xx]){
  448.         //RESRC[NI][1]-=xcost;
  449.         OBJ->Nat->CreateTerrainAt(xx,yy,OBJ->LocalOrder->info.Produce.ObjIndex);
  450.         if(OBJ->DstX&&LastObject!=0xFFFF)PerformAction(Group[LastObject],OBJ->DstX,OBJ->DstY);
  451.     };
  452.     if(int(OBJ->InLineCom))OBJ->FreeAsmLink();
  453.     if(int(OBJ->LocalOrder)){
  454.         Order1* Or1=OBJ->LocalOrder->NextOrder;
  455.         OBJ->FreeOrdBlock(OBJ->LocalOrder);
  456.         OBJ->LocalOrder=Or1;
  457.         OBJ->Important=false;
  458.     };
  459. };
  460. int GetAmount(word ID){
  461.     word CID=0;
  462.     word Nsel=NSL[MyNation];
  463.     word* SMon=Selm[MyNation];
  464.     for(int i=0;i<Nsel;i++){
  465.         word MID=SMon[i];
  466.         if(MID!=0xFFFF){
  467.             OneObject* OBJ=Group[MID];
  468.             if(int(OBJ)){
  469.                 Order1* OR1=OBJ->LocalOrder;
  470.                 while(int(OR1)){
  471.                     if(OR1->OrderType==13&&
  472.                         OR1->info.Produce.ObjIndex==ID)CID++;
  473.                     OR1=OR1->NextOrder;
  474.                 };
  475.             };
  476.         };
  477.     };
  478.     return CID;
  479. };
  480. int GetProgress(word ID){    
  481.     word CID=0;
  482.     word Nsel=NSL[MyNation];
  483.     word* SMon=Selm[MyNation];
  484.     for(int i=0;i<Nsel;i++){
  485.         word MID=SMon[i];
  486.         if(MID!=0xFFFF){
  487.             OneObject* OBJ=Group[MID];
  488.             if(int(OBJ)){
  489.                 Order1* OR1=OBJ->LocalOrder;
  490.                 if(int(OR1)&&OR1->OrderType==13&&
  491.                     OR1->info.Produce.ObjIndex==ID&&
  492.                     OR1->info.Produce.Progress>CID)
  493.                     CID=OR1->info.Produce.Progress;
  494.             };
  495.         };
  496.     };
  497.     return CID;
  498. };