#include <stdio.h>
#include <dos.h>
#include <math.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include "3dproj.h"
#include "3ddefs.h"
#include "3dprep.h"
#include "3dvarse.h"

void safelineellipse(int c,int x, int y, int rx, int ry)
{
  int px;
  float rxrx,tempa,tempb;

  if((rxrx=rx*rx)<1) return;
  for(px=-rx;px<=0;px++)
  {
    tempa=ry*sqrt(1-((px*px)/rxrx));
    tempb=ry*sqrt(1-(((px+1)*(px+1))/rxrx));
    if(y+tempa>=0 && y+tempa<200 && y+tempb>=0 && y+tempb<200)
    {
      if(x+px>=0 && x+px<320) apiline(c,x+px,y+tempa,x+px,y+tempb);
      if(x-px>=0 && x-px<320) apiline(c,x-px,y+tempa,x-px,y+tempb);
    }
    if(y-tempa>=0 && y-tempa<200 && y-tempb>=0 && y-tempb<200)
    {
      if(x+px>=0 && x+px<320) apiline(c,x+px,y-tempa,x+px,y-tempb);
      if(x-px>=0 && x-px<320) apiline(c,x-px,y-tempa,x-px,y-tempb);
    }
  }
}

void  safefillellipse(int c,int x, int y, int rx, int ry)
{
  int px,i,xstart,xend;
  float rxrx,tempa,tempb,temp;

  if((rxrx=rx*rx)<1) return;
  for(px=-rx;px<=0;px++)
  {
    tempa=ry*sqrt(1-((px*px)/rxrx));
    tempb=ry*sqrt(1-(((px+1)*(px+1))/rxrx));
    if(tempa>tempb) { temp=tempa; tempa=tempb; tempb=temp; }
    for(i=tempa;i<=tempb;i++)
    {
      if(y+i>=0 && y+i<200 && x+px<320 && x-px>=0)
      {
        if(x+px<0) xstart=0;
        else xstart=x+px;
        if(x-px>319) xend=319;
        else xend=x-px;
        apiline(c,xstart,y+i,xend,y+i);
      }
      if(y-i>=0 && y-i<200 && x+px<320 && x-px>=0)
      {
        if(x+px<0) xstart=0;
        else xstart=x+px;
        if(x-px>319) xend=319;
        else xend=x-px;
        apiline(c,xstart,y-i,xend,y-i);
      }
    }
  }
}

void  moveyourguns(void)
{
  int f;
  float gunsem,gunrotz,gunz;
  float jx,jy;

  jx=(judx/2)+o[0].rsz*4;
  jy=(judy/2)+o[0].rsx*4;
  if (o[0].crashzones==0) for (f=0; f<o[0].guns; f++)
  {
    if (o[0].g[f].type==LASER || o[0].g[f].type==TURBOLASER)
    {
      if (o[0].g[f].fireframe<3 && o[0].g[f].fireframe>0 && o[0].g[f].fireflag==-1) gunsem=1;
      else gunsem=0;
      if (o[0].g[f].fireframe==0 || o[0].g[f].fireflag==1) gunz=70;
      else gunz=25+o[0].g[f].fireframe*7;
      apicockpitshape(DRAWFULL,rgun[f],gunsem, (o[0].g[f].gun*200)+jx,40+jy,gunz+40, 0 , 0 , 0 );
      if (o[0].g[f].fireframe<3 && o[0].g[f].fireframe>0 && o[0].g[f].fireflag==1) gunsem=1;
      else gunsem=0;
      if (o[0].g[f].fireframe==0 || o[0].g[f].fireflag==-1) gunz=70;
      else gunz=25+o[0].g[f].fireframe*7;
      apicockpitshape(DRAWFULL,lgun[f],gunsem, (-o[0].g[f].gun*200)+jx,40+jy,gunz+40, 0 , 0 , 0 );
    }
    if (o[0].g[f].type==ION)
    {
      if (o[0].g[f].fireframe>ioncharge) gunrotz=65535L*(o[0].g[f].fireframe-ioncharge)/(gunrate[ION]-ioncharge);
      else gunrotz=0;
      if (((o[0].g[f].fireframe<ioncharge && o[0].g[f].fireframe>0)&& (key[_R_CTRL] || apibuttons==1)) && o[0].g[f].fireflag==-1) gunz=50+frame2*10;
      else gunz=70;
      apicockpitshape(DRAWFULL,rgun[f],Semaphores, (o[0].g[f].gun*200)+jx,40+jy,gunz, 0 , 0 , gunrotz );
      if ((o[0].g[f].fireframe<ioncharge && o[0].g[f].fireframe>0 && (key[_R_CTRL] || apibuttons==1)) && o[0].g[f].fireflag==1) gunz=50+frame2*10;
      else gunz=70;
      apicockpitshape(DRAWFULL,lgun[f],Semaphores,(-o[0].g[f].gun*200)+jx,40+jy,gunz, 0 , 0 , -gunrotz );
    }
    if (o[0].g[f].type==CHAINGUN)
    {
      gunrotz=(o[0].g[f].fireflag+=o[0].g[f].fireframe)*300;
      gunz=100;
      gunsem=0;
      if (o[0].g[f].fireframe>29 && o[0].g[f].left>0)
      {
        if (frame2==0) gunsem=1;
        gunz=90+(frame2*5);
      }
      apicockpitshape(DRAWFULL,rgun[f],gunsem,( o[0].g[f].gun*200)+jx,40+jy,gunz, 0 , 0 , gunrotz );
      apicockpitshape(DRAWFULL,lgun[f],gunsem,(-o[0].g[f].gun*200)+jx,40+jy,gunz, 0 , 0 , -gunrotz );
    }
  }
  if(judx!=0 || judy!=0)
  {
     if(judx>1 || judx<-1 || judy>1 || judy<-1)
    {
      judx=judx/1.5;
      judy=judy/1.5;
    }
    else
    {
      judx=judy=0;
    }
  }
  if(o[0].doing!=10) f=0; else f=frame2;
//  if(drawcockpit==1) apicockpitshape(DRAWFULL,cockpit,0,judx+o[0].rsz*9,judy+o[0].rsx*5,0,0,0,o[0].rsz*1000);
  if(drawcockpit==1) apicockpitshape(DRAWFULL,cockpit,0,judx+o[0].rsz*9,judy+o[0].rsx*6,200,0,0,0);
  apicockpitshape(DRAWFULL,cock,f,judx+o[0].rsz*10,judy+o[0].rsx*5,260,0,0,0);
  if (targetinfo<10)
  {
    if(targetinfoupdown==10) targetinfo++; //going down - 0 is up 10 is down
    if(targetinfo>0 &&targetinfoupdown==0) targetinfo--; //going up
    apicockpitshape(DRAWFULL,targetbox,0,-3+judx+o[0].rsz*10,o[0].rsx*5+judy-2+targetinfo*4,254,0,0,0);
  }
  if ((view<=3 && o[0].shields<o[0].maxshields/2 && frame1<5 && o[0].doing!=10 && drawcockpit==1) || o[0].doing==DIEING)
  { // red flash
    apicockpitshape(DRAWFULL,red,0,0,0,200,0,0,0);
  }
}

void  updatescanner(void)
{
  char s1[40],s2[40];
  int f,g,h,x,i;
  float xold,yold,xold2,yold2,zold,length,factor;
  float jx,jy;
  int fore,back;
  jx=judx+o[0].rsz*10;
  jy=judy+o[0].rsx*5;
  for (f=1; f<ships; f++)
  {
    if (f==o[0].mother && o[0].doing==LANDING && o[f].cz>10 && o[f].hangerzones>0)
    {
      if (frame1<5) g=120;
      else g=141;
      xold=(256/ar)*((o[f].cx+o[f].h[o[0].motherhangerzone].cx)/(o[f].cz+o[f].h[o[0].motherhangerzone].cz));
      yold=(256/ar)*((o[f].cy+o[f].h[o[0].motherhangerzone].cy)/(o[f].cz+o[f].h[o[0].motherhangerzone].cz));
      if(xold>-150 && xold<150 && yold>-90 && yold<90)
      {
        apiline(g,158+xold,(100+yold),154+xold,(100+yold));
        apiline(g,162+xold,(100+yold),166+xold,(100+yold));
        apiline(g,158+xold,(99+yold),158+xold,(101+yold));
        apiline(g,162+xold,(99+yold),162+xold,(101+yold));
      }
    }
    if(o[f].target==0 && o[f].type>-1 && o[f].cz>10 ) // Show all incominG ships
    {
      xold=(256/ar)*o[f].cx/o[f].cz;
      yold=(256/ar)*o[f].cy/o[f].cz;
      if(frame1<5) g=160+(frame1*2);
      else g=160+(20-(frame1*2));
      if(xold>-150 && xold<150 && yold>-60 && yold<60)
      {
        apiline(g,158+xold,(100+yold),156+xold,(100+yold));
        apiline(g,162+xold,(100+yold),164+xold,(100+yold));
        apiline(g,158+xold,(99+yold),158+xold,(101+yold));
        apiline(g,162+xold,(99+yold),162+xold,(101+yold));
      }
    }
    if (o[f].type>-1 && (o[f].cz>10 || o[f].cz<-10))
    {
      if (o[f].target==0 && o[f].guns>0 && o[0].side<5 ) // Dunno. Crashes without o[0].side<5 when your side changes. Bitching.
      {
        if (o[f].g[0].fireframe>0 && frame1<5) g=1;
        else g=209;
      }
      else if (o[f].side==1 || o[f].side==6) g=194;
      else if (o[f].side==2 || o[f].side==7) g=145;
      else g=7;
      if (o[f].cz<0) xold2=168;
      else xold2=-98;
      xold=4*o[f].cx/o[f].cz;
      yold=4*o[f].cy/o[f].cz;

      if (xold>-22 && xold<22 && yold>-18 && yold<18)
      {
        apiplot(g,xold2+125+xold+jx,(22+yold)+jy);
        if (o[f].target==0)
        {
          apiline(g,xold2+124+(xold)+jx,(22+yold)+jy,xold2+126+(xold)+jx,(22+yold)+jy);
        }
        if (f==o[0].target)
        {
          if (frame1>4) zold=2;
          else zold=1;
          apiline(zold,xold2+124+(xold)+jx,(22+yold)+jy,xold2+126+(xold)+jx,(22+yold)+jy);
          apiline(zold,xold2+125+(xold)+jx,(23+yold)+jy,xold2+125+(xold)+jx,(21+yold)+jy);
        }
      }
    }
  } // End of loop through ships

  //Text for incoming missile */
  if (incoming==4)
  {
    if (frame1<5) apiniceprint3(209,160,137+jx,90+jy,"MISSILE LOCK");
    if (frame2==1 && soundblaster==1 && fx==1)
    {
      playing[13]=0;
      playsoundeffect(13,0);
    }
    for(f=0;f<shapes-10;f++)
    {
      if(p[f].target==0 && ((p[f].type>=103 && p[f].type<=106)) && p[f].cz>10 ) // Show all incoming
      {
        xold=(256/ar)*p[f].cx/p[f].cz;
        yold=(256/ar)*p[f].cy/p[f].cz;
        if (frame2==1) g=209;
        else g=2;

        if(xold>-150 && xold<150 && yold>-60 && yold<60)
        {
          apiline(g,158+xold,(100+yold),146+xold,(100+yold));
          apiline(g,162+xold,(100+yold),174+xold,(100+yold));
          apiline(g,158+xold,(99+yold),158+xold,(101+yold));
          apiline(g,162+xold,(99+yold),162+xold,(101+yold));
        }
      }
    }
  }
  // Text for landing
  if (o[0].doing==LANDING && frame1>=5) apigameprint3(209,140+jx,107+jy,"GEAR DOWN");
  // Text for hyperspacing
  if (o[0].doing==ENTERING_HYPERSPACE)
  {
    if(ground>0 && gr[4].dy[0]<0) o[0].doing=NORMAL;
    if (o[0].frame1>0)
    {
      playtricia(7);
      sprintf(s1,"ACCELERATION COMMIT:%d",o[0].frame1);
      apiniceprint3(209,160,120+jx,107+jy,s1);
    }
    else if (frame1>=5)
    {
      playtricia(8);
      apigameprint3(2,120+jx,107+jy,"ACCELERATION COMMITED");
    }
  }
  // crosshairs for people that are talking
  if (commtimer>0 && currentprintcomm>0 && c[currentprintcomm].from>0 && o[c[currentprintcomm].from].cz>10 && o[c[currentprintcomm].from].type>0)
  {
    xold=(256/ar)*o[c[currentprintcomm].from].cx/o[c[currentprintcomm].from].cz;
    yold=(256/ar)*o[c[currentprintcomm].from].cy/o[c[currentprintcomm].from].cz;
    if (xold>-140 && xold<140 && yold>-70 && yold<50)
    {
      apiline(112+frame1*3,158+xold,(98+yold-frame1*2),162+xold,(98+yold-frame1*2));
      apiline(112+frame1*3,158+xold-frame1*3,98+yold,158+xold-frame1*3,102+yold);
      apiline(112+frame1*3,158+xold,(102+yold+frame1*2),162+xold,(102+yold+frame1*2));
      apiline(112+frame1*3,162+xold+frame1*3,98+yold,162+xold+frame1*3,102+yold);
      apiline(112+frame1*3,162+xold,(98+yold-frame1*2),162+xold+frame1*3,98+yold);
      apiline(112+frame1*3,162+xold,(102+yold+frame1*2),162+xold+frame1*3,102+yold);
      apiline(112+frame1*3,158+xold,(98+yold-frame1*2),158+xold-frame1*3,98+yold);
      apiline(112+frame1*3,158+xold,(102+yold+frame1*2),158+xold-frame1*3,102+yold);
    }
  }

  // draw vertical target crosshairs if target is infront
  if (o[0].target>-1 && o[o[0].target].type>-1 && o[o[0].target].cz>10)
  {
    xold=(o[o[0].target].cx*(256/ar))/o[o[0].target].cz;
    yold=(o[o[0].target].cy*(256/ar))/o[o[0].target].cz;
    if (o[o[0].target].side==o[0].side) {i=210;h=99;}
    else {i=213;h=219;}
    if(tat>0) tat--;
    if (xold>-150 && xold<150 && yold>-60 && yold<40) //Make sure is on screen
    {
      if(tat>0)
      {
        if((90+yold-(tat*5))>40) apiline(176+tat*1.5,160+xold,(90+yold-(tat*5)), 160+xold,(95+yold-(tat*5)));
        if((90+yold+(tat*5))<140) apiline(176+tat*1.5,160+xold,(105+yold+(tat*5)),160+xold,(110+yold+(tat*5)));
        if((159+xold+(tat*7))<310) apiline(176+tat*1.5,159+xold+(7*tat),(105+yold),161+xold+(7*tat),(105+yold));
        if((159+xold-(tat*7))>10) apiline(176+tat*1.5,159+xold-(7*tat),(105+yold),161+xold-(7*tat),(105+yold));
        if((159+xold+(tat*7))<310) apiline(176+tat*1.5,159+xold+(7*tat),(95+yold),161+xold+(7*tat),(95+yold));
        if((159+xold-(tat*7))>10) apiline(176+tat*1.5,159+xold-(7*tat),(95+yold),161+xold-(7*tat),(95+yold));
        for(g=0; g<o[o[0].target].turrets; g++)
        {
          if(frame1==0) targetturretflash++;
          if(targetturretflash>=o[o[0].target].turrets) targetturretflash=0;
          xold2=(256/ar)*((o[o[0].target].cx+o[o[0].target].t[g].cx)/(o[o[0].target].cz+o[o[0].target].t[g].cz));
          yold2=(256/ar)*((o[o[0].target].cy+o[o[0].target].t[g].cy)/(o[o[0].target].cz+o[o[0].target].t[g].cz));
          if(xold2>-150 && xold2<150 && yold2>-90 && yold2<90)
          {
            apiline(223-tat,158+xold2,(100+yold2),156+xold2,(100+yold2));
            apiline(223-tat,162+xold2,(100+yold2),164+xold2,(100+yold2));
            apiline(223-tat,158+xold2,(99+yold2),158+xold2,(101+yold2));
            apiline(223-tat,162+xold2,(99+yold2),162+xold2,(101+yold2));
          }
        }
      }
      else
      {
        apiline(h,160+xold,(105+yold),160+xold,(110+yold));
        apiline(h,160+xold,(95+yold),160+xold,(90+yold));
        apiline(i,159+xold,(105+yold),161+xold,(105+yold));
        apiline(i,159+xold,(95+yold),161+xold,(95+yold));
        if(o[o[0].target].turrets>0)
        {
          g=targetturret;
          if(o[o[0].target].side==o[0].side) h=160;
          else h=213;
          xold2=(256/ar)*((o[o[0].target].cx+o[o[0].target].t[g].cx)/(o[o[0].target].cz+o[o[0].target].t[g].cz));
          yold2=(256/ar)*((o[o[0].target].cy+o[o[0].target].t[g].cy)/(o[o[0].target].cz+o[o[0].target].t[g].cz));
          if(xold2>-150 && xold2<150 && yold2>-90 && yold2<90)
          {
            apiline(h,160+xold2,(101+yold2),160+xold2,(103+yold2));
            apiline(h,160+xold2,(97+yold2),160+xold2,(99+yold2));
            apiline(h,159+xold2,(99+yold2),161+xold2,(99+yold2));
            apiline(h,159+xold2,(101+yold2),161+xold2,(101+yold2));
          }
        }
      }
    }
    else // Draw a little arrow pointing to him if off the screen
    {
      if (xold<-155) xold=-155;
      if (xold>155) xold=155;
      if (yold<-55) yold=-55;
      if (yold>55) yold=55;
      if (frame1>7) h=210;
      apiline(h,160+xold+jx,(100+yold+jy),(160+xold/1.1)+jx,(100+yold/1.1)+jy);
      apiline(h,157+xold+jx,(100+yold+jy),163+xold+jx,(100+yold)+jy);
      apiline(h,160+xold+jx,(97+yold+jy),160+xold+jx,(103+yold)+jy);
    }
  }
  if (frame1==1) // every ten frames, calculate mission stats
  {
    enemy=0; friendly=0; neutral=0; total=0;
    enemypower=0; friendlypower=0; neutralpower=0; totalpower=0;
    for (f=0; f<ships; f++)
    {
      if ((o[f].type>-1)&&(o[f].shape!=36)&&(o[f].shape!=37)&&(o[f].shape!=38)&&(o[f].doing!=10))
      {
        total++;
        if (o[f].side==o[0].side)
        {
          friendly++; friendlypower+=o[f].shields+o[f].armour; totalpower+=o[f].shields+o[f].armour;
        }
        else if (o[f].side!=o[0].side)
        {
          enemy++; enemypower+=o[f].shields+o[f].armour; totalpower+=o[f].shields+o[f].armour;
        }
      } // End of existing ship
    } // End of count ships.
  } // End of count vitals

  // Fill in stats on left
  if (total>0 && totalpower>0 ) // Side power status
  {
    if(o[0].side==1 || o[f].side==6) drawpowerbar(friendly,friendlypower,3,205);
    else if(o[0].side==2 || o[f].side==7) drawpowerbar(friendly,friendlypower,3,154);
    else drawpowerbar(friendly,friendlypower,3,7);
    drawpowerbar(enemy,enemypower,10,2);
  }

  //Do amo on right of screen
  for (g=0; g<o[0].guns; g++)
  {
    if (o[0].g[g].selected==1)// selected
    {
      if (o[0].g[g].fireframe>1) h=209; // firing - yellow
      else h=152; // selected not firing - red
    }
    else h=101; // not selected - green
    x=183+(g*5)-(o[0].guns*2);
    apibox(h,236+jx,x+jy,241+jx,(x+3)+jy);
    switch(o[0].g[g].type)
    {
      case LASER:
          if(o[0].side==1 || o[0].side==6) h=2; else h=147;
          for(i=0; i<(gunrate[LASER]-o[0].g[g].fireframe); i++)
          {
            apiline(h,(243+i*8)+jx,x+jy,(247+i*8)+jx,x+jy);
            apiline(h,(243+i*8)+jx,(x+3)+jy,(247+i*8)+jx,(x+3)+jy);
          }
        break;
      case BEAM:
          if(o[0].side==1 || o[f].side==6) h=209; else h=2;
          apiline(h,243+jx,(x+1)+jy,257+jx,(x+1)+jy);
          apiline(h,243+jx,(x+3)+jy,257+jx,(x+3)+jy);
        break;
      case ION:
        for(i=0; i<(ioncharge-o[0].g[g].fireframe)/2.5; i++)
        {
          apiplot(112,(243+i*2)+jx,x+jy);
          apiplot(112,(243+i*2)+jx,(x+3)+jy);
        }
        for(i=0; i<(o[0].g[g].fireframe)/3.75; i++)
        {
          apiplot(130,(244+i*2)+jx,x+jy);
          apiplot(130,(244+i*2)+jx,(x+3)+jy);
        }
        break;
      case BOMB:
        for(i=0; i<o[0].g[g].left; i++) apibox(43,(243+i*3)+jx,(x+1)+jy,(244+i*3)+jx,(x+2)+jy);
        break;
      case NUKE:
          for(i=0; i<o[0].g[g].left; i++) apibox(7,(243+i*4)+jx,(x+1)+jy,(245+i*4)+jx,(x+2)+jy);
        break;
      case TORP:
          for(i=0; i<o[0].g[g].left; i++) apibox(2,(243+i*3)+jx,(x+1)+jy,(244+i*3)+jx,(x+2)+jy);
        break;
      case MISSILE:
          for(i=0; i<o[0].g[g].left; i++)
          {
            apiline(40,(244+i*5)+jx,(x+2)+jy,(246+i*5)+jx,(x+2)+jy);
            apiline(42,(243+i*5)+jx,(x+1)+jy,(244+i*5)+jx,(x+1)+jy);
            apiline(39,(243+i*5)+jx,(x+3)+jy,(244+i*5)+jx,(x+3)+jy);
          }
        break;
      case TURBOLASER:
          for(i=0; i<(gunrate[TURBOLASER]-o[0].g[g].fireframe); i++)
          {
            apiline(203,(243+i*8)+jx,x+jy,(247+i*8)+jx,x+jy);
            apiline(203,(243+i*8)+jx,(x+3)+jy,(247+i*8)+jx,(x+3)+jy);
          }
        break;
      case CHAINGUN:
          for(i=0; i<o[0].g[g].left/10; i++)
          {
            apiplot(160+i/2,(243+i*2)+jx,x+jy);
            apiplot(160+i/2,(243+i*2)+jx,(x+3)+jy);
          }
        break;
    }
  }

  //Fill in power bars on right
  if (o[0].maxshields>1) for (f=0; f<(o[0].shields/(o[0].maxshields)) * 25; f=f+2) // Ship power
    apiline(159-(f/5) ,298+jx, (196-f)+jy ,302+jx, (196-f)+jy);
  if (o[0].maxarmour>1) for (f=0; f<(o[0].armour/(o[0].maxarmour)) * 25; f=f+2)
    apiline(160+(f/5) ,305+jx, (196-f)+jy ,309+jx, (196-f)+jy);
  if (o[0].topspeed>1) for (f=0; f<(o[0].speed/o[0].topspeed) * 25; f=f+2)
    apiline( 143-(f/2.5),311+jx, (196-f)+jy ,315+jx, (196-f)+jy);
  if(targetinfo<10) //Moving or fully up
  {
    safefillellipse(0,102+jx,(175+4*targetinfo)+jy,15,13);
    safelineellipse(154,102+jx,(175+4*targetinfo)+jy,15,13);
  }
  if(targetinfo==0) //Up, so draw fullay and fill it in.
  {
    if(o[0].target>0 && o[o[0].target].type>-1) //Draw the target information
    {
      apiclearobjects(); // ship in window thing at bottom
      if(o[o[0].target].shape==90 || o[o[0].target].shape==91 || o[o[0].target].shape==92 || o[o[0].target].shape==93 || o[o[0].target].shape==98)
        apicockpitshape(DRW_SIMPLE,targ,0,(shapedata[o[o[0].target].shape].scale*-385)+(jx*shapedata[o[o[0].target].shape].scale*8),(500*shapedata[o[o[0].target].shape].scale)+(jy*shapedata[o[o[0].target].shape].scale*8),1700*shapedata[o[o[0].target].shape].scale, -5000,0,0);
      else
        apicockpitshape(DRW_SIMPLE,targ,0,
        (shapedata[o[o[0].target].shape].scale*-(385*1.2))
        +(jx*shapedata[o[o[0].target].shape].scale*(8*1.2)),
        ((500*1.2)*shapedata[o[o[0].target].shape].scale)+
        (jy*shapedata[o[o[0].target].shape].scale*(8*1.2)),
        (1700*1.2)*shapedata[o[o[0].target].shape].scale,
        o[o[0].target].rx,o[o[0].target].ry,o[o[0].target].rz);
      apidrawobjects();

      switch(o[o[0].target].side)
      {
        case -1:
          fore=23;
          back=38;
        break;
        case 0:
          fore=23;
          back=38;
        break;
        case 1:
          fore=128;
          back=136;
        break;
        case 2:
          fore=147;
          back=154;
        break;
        case 3:
          fore=176;
          back=182;
        break;
        case 5:
          fore=96;
          back=104;
        break;
        case 4:
          fore=80;
          zold=88;
        break;
      }
      apiniceprint3(fore,back,135+jx,164+jy,o[o[0].target].name);
      xold=sqrt(o[o[0].target].dz[0]*o[o[0].target].dz[0])/8;
      yold=sqrt(o[o[0].target].dy[1]*o[o[0].target].dy[1])/8;
      safelineellipse(152,102+jx,175+jy,xold,13);
      safelineellipse(150,102+jx,175+jy,15,yold);
      if (o[o[0].target].shape!=36 && o[o[0].target].shape!=37 && o[o[0].target].shape!=38)
      {
        if (o[o[0].target].maxshields>1) for (f=0; f<(o[o[0].target].shields/o[o[0].target].maxshields*25); f=f+2)
          apiline(159-(f/5) ,120+jx,(188-f)+jy,124+jx,((188-f)+jy));
        if (o[o[0].target].maxarmour>1) for (f=0; f<(o[o[0].target].armour/o[o[0].target].maxarmour*25); f=f+2)
          apiline(160+(f/5) ,126+jx,(188-f)+jy,130+jx,((188-f)+jy));
        apigameprint3(159,121+jx,192+jy,"S");
        apigameprint3(160,127+jx,192+jy,"A");
      }

      gcvt(pythag3d(o[o[0].target].cz,o[o[0].target].cy,o[o[0].target].cx),5,s1);
      strcat(s1,"M");
      apigameprint3(25,89+jx,192+jy,s1);
      if (matter[o[0].target]==1) apiniceprint3(fore,back,135+jx,188+jy , "MISSION OBJECTIVE" );
      else if (matter[o[0].target]==2) apiniceprint3(fore,back,135+jx,188+jy , "MISSION CHARGE" );
      if (targetstatistics==1)
      {
        sprintf(s1,"%s CLASS",shapedata[o[o[0].target].shape].name);
        apiniceprint3(fore,back,135+jx,170+jy,s1);
        sprintf(s1,"%s",shapedata[o[o[0].target].shape].type);
        apiniceprint3(fore,back,135+jx,176+jy,s1);

        yold=0;
        switch(o[o[0].target].type) //Fighter action
        {
          case TYPE_NOTHING: sprintf(s1,"\0"); break;
          case TYPE_NORMAL:
          case TYPE_NONSENTIENT:
          case TYPE_APPROXIMATE:
          case TYPE_BROADSIDE:
            switch(o[o[0].target].doing)
            {
              case ATTACKING:
                if (o[o[0].target].target==TYPE_NOTHING) strcpy(s1,"SCANNING ");
                else sprintf(s1,"ATTACK: %s",shapedata[o[o[o[0].target].target].shape].type);
                yold=1;
                break;
              case WITHDRAWING:
                if (o[o[0].target].target==TYPE_NOTHING) strcpy(s1,"SCANNING ");
                else sprintf(s1,"TARGET: %s",shapedata[o[o[o[0].target].target].shape].type);
                yold=1;
                break;
              case EVADING:
                if (o[o[0].target].target==TYPE_NOTHING) strcpy(s1,"PANICING");
                else sprintf(s1,"EVADE : %s",shapedata[o[o[o[0].target].target].shape].type);
                yold=1;
                break;
              case APPROACHING: sprintf(s1,"APPROACH: %s",shapedata[o[o[o[0].target].mother].shape].type); yold=2;break;
              case LININGUP: sprintf(s1,"LINEUP: %s",shapedata[o[o[o[0].target].mother].shape].type); yold=2;break;
              case LANDING: sprintf(s1,"DOCK: %s",shapedata[o[o[o[0].target].mother].shape].type); yold=2;break;
              case PREPARINGTOBOARD: sprintf(s1,"APPROACH: %s",shapedata[o[o[o[0].target].mother].shape].type); yold=2;break;
              case BOARDING: sprintf(s1,"BOARDING: %s",shapedata[o[o[o[0].target].mother].shape].type); yold=2;break;
              case BOARDED:
                if (o[o[0].target].frame1<100*shapedata[o[o[o[0].target].mother].shape].scale) sprintf(s1,"BOARDED: %s",shapedata[o[o[o[0].target].mother].shape].type);
                else sprintf(s1,"CAPTURED: %s",shapedata[o[o[o[0].target].mother].shape].type);
                yold=2;
                break;
              case DIEING: strcpy(s1,"OUT OF CONTROL "); break;
              case LEAVING_HYPERSPACE: strcpy(s1,"ENTERING BATTLEFIELD "); break;
              case ENTERING_HYPERSPACE: strcpy(s1,"LEAVING BATTLEFIELD "); break;
            }
            break;
          case TYPE_DERELICT:
          case TYPE_AMBUSH:
            strcpy(s1,"DERELICT");
            break;
          case TYPE_CONVOY:
          case TYPE_DUMBCONVOY:
              strcpy(s1,"KEEPING FORMATION ");
            break;
        }

        f=0;
        strcpy(s2,"");
        while( s1[f]!=':' && f<strlen(s1))
        {
          s2[f]=s1[f];
          f++;
        }
        s2[f]=s1[f];
        f++;
        s2[f]=' ';
        s2[f+1]='\0';
        apiniceprint3(fore,back,135+jx,182+jy,s2);
        xold=(f)*4;
        strcpy(s2,"");
        if(yold==1 || yold==2)
        {
          if(yold==1) g=(o[o[o[0].target].target].side);
          if(yold==2) g=(o[o[o[0].target].mother].side);
          switch(g)
          {
            case -1:
              fore=23;
              back=38;
            break;
            case 0:
              fore=23;
              back=38;
            break;
            case 1:
              fore=128;
              back=136;
            break;
            case 2:
              fore=147;
              back=154;
            break;
            case 3:
              fore=176;
              back=182;
            break;
            case 5:
              fore=96;
              back=104;
            break;
            case 4:
              fore=80;
              zold=88;
            break;
          }
          g=0;
          while (f<strlen(s1))
          {
            s2[g]=s1[f];
            f++; g++;
          }
          s2[g]='\0';
          apiniceprint3(fore,back,135+jx+(xold),182+jy,s2);
        }
      }

    }
    if(targetinfoupdown==10) targetinfo++; //going up - 0 is up
  }
  else if(targetinfo==10 && targetinfoupdown==0) targetinfo--;

  //Cross hairs in middile of screen
  if(ground==0)
  {
    apiline(219,150+jx,100+jy,155+jx,100+jy);
    apiline(219,165+jx,100+jy,170+jx,100+jy);
    apiline(213,155+jx,99+jy,155+jx,101+jy);
    apiline(213,165+jx,99+jy,165+jx,101+jy);
  }
  else
  {
    xold=((gr[4].dy[1] )/40);
    yold=((-gr[4].dx[1] )/40);
    length=pythag2d(xold,yold);
    factor=20/length;
    xold=xold*factor;
    yold=yold*factor;
    apiline(219,jx+160-xold/4.5,jy+100-yold/3.5,
                jx+160-xold/2,jy+100-yold/2);
    apiline(219,jx+160+xold/4.5,jy+100+yold/3.5,
              jx+160+xold/2,jy+100+yold/2);
    apiline(213,jx+160-(xold/4.5)+(-yold/15),
                jy+100-(yold/4.5)+(xold/15),
                jx+160-(xold/4.5)-(-yold/15),
                jy+100-(yold/4.5)-(xold/15));
    apiline(213,jx+160+(xold/4.5)-(-yold/15),
                jy+100+(yold/4.5)-(xold/15),
                jx+160+(xold/4.5)+(-yold/15),
                jy+100+(yold/4.5)+(xold/15));

    xold2=height/55;
    if(xold2>50) xold2=50;
    apiline(213,jx+160-(xold/4.5)+(-yold/15)*xold2,
                jy+100-(yold/4.5)+(xold/15)*xold2,
                jx+160+(xold/4.5)+(-yold/15)*xold2,
                jy+100+(yold/4.5)+(xold/15)*xold2);
  }
}

void  drawpowerbar(int teamnum, float teampower,int xoffset,int color)
{
  int f,h;
  char s1[20];
  float jx,jy;
  jx=judx+o[0].rsz*10;
  jy=judy+o[0].rsx*5;
  if (teamnum>0)
  {
    if(teamnum<10) sprintf(s1,"%1d",teamnum);
    else sprintf(s1,"X");
    f=teampower*19/totalpower;
    if (f<1) f=1;
    if (f>40) f=40;
    apigameprint3(color,xoffset+1+jx,192+jy,s1);
    for (h=190; h>190-f; h-=2) apiline(color,xoffset+jx,h+jy,xoffset+4+jx,h+jy);
  }
}

void  printcomputer(int completed, int notcompleted, int critical)
{
  int yold=1,zold=2,f;
  float jx,jy;
  jx=judx+o[0].rsz*10;
  jy=judy+o[0].rsx*5;
  if (complatesttimer>0) complatesttimer++;
  if (complatesttimer>30) complatesttimer=0;
  for (f=0; f<4; f++)
  {
    if (frame1<5 && ((complatesttimer>0 && f==3) || (complatesttimer>0 && f==2 &&
    (!strcmp(comp[f+1],"DESTROYED.") ||!strcmp(comp[f+1],"COMPLETED.")||
     !strcmp(comp[f+1],"CRITICAL!")||!strcmp(comp[f+1],"FAILURE.") ||
     !strcmp(comp[f+1],"HAS ARRIVED.") || !strcmp(comp[f+1],"HAS LEFT.") ||
     !strcmp(comp[f+1],"BOARDED.") || !strcmp(comp[f+1],"HAS DOCKED.") ||
     !strcmp(comp[f+1],"CAPTURED.")))))
    {
      yold=2;
      zold=103;
    }
    else
    {
      switch(compside[f])
      {
        case -1:
          yold=23;
          zold=38;
        break;
        case 0:
          yold=23;
          zold=38;
        break;
        case 1:
          yold=128;
          zold=136;
        break;
        case 2:
          yold=147;
          zold=154;
        break;
        case 3:
          yold=176;
          zold=182;
        break;
        case 5:
          yold=96;
          zold=104;
        break;
        case 4:
          yold=80;
          zold=88;
        break;
      }
    }
    apiniceprint3(yold,zold,24+jx,(173+f*6)+jy, comp[f] );
  }
  if (critical==1 && complatest!=1 && complatest!=2)
  {
    complatest=1;
    addcomputer("MISSION",-1);
    addcomputer("CRITICAL!",-1);
    playtricia(4);
  }
  if (completed==1 && complatest!=2)
  {
    complatest=2;
    addcomputer("MISSION",-1);
    addcomputer("COMPLETED.",-1);
    playtricia(5);
  }
  if (notcompleted==1 && complatest!=2)
  {
    complatest=2;
    addcomputer("MISSION",-1);
    addcomputer("FAILURE.",-1);
    playtricia(6);
  }
}

void  addcomputer(char s1[40], int side)
{
  int f;
  for (f=1; f<4; f++)
  {
    strcpy(comp[f-1],comp[f]);
    compside[f-1]=compside[f];
  }
  strcpy(comp[3],s1);
  compside[3]=side;
  complatesttimer=1;
}

void  drawstarfield(float rsx,float rsy,float rsz)
{
  int f;
  float cax,sax,cay,say,caz,saz;
  cax=cos(a*rsx);
  cay=cos(a*rsy);
  caz=cos(a*rsz);
  sax=sin(a*rsx);
  say=sin(a*rsy);
  saz=sin(a*rsz);
  for (f=0; f<starfield; f++)
  {
    rotatesummatelse(&star[f].x,&star[f].y,&star[f].z,cax,sax,cay,say,caz,saz);
    apishape(DRW_SIMPLE,star[f].object,0, viewx-star[f].x,viewy-star[f].y,viewz-star[f].z,viewrx,viewry,viewrz+8000);
    apishape(DRW_SIMPLE,star[f].object,0, viewx+star[f].x,viewy+star[f].y,viewz+star[f].z,viewrx,viewry,viewrz+8000);
  }
}

void  drawplanets(void)
{
  int f;
//  spinprojectile(shapes-10, 0,0,0, o[0].rsx,o[0].rsy,o[0].rsz,0);
  dddRotateTo(light,p[shapes-9].rx,p[shapes-9].ry,p[shapes-9].rz);
//  if (p[shapes-9].type>-1)
//    apiplanet(p[shapes-9].object,p[shapes-9].shape,viewx+p[shapes-9].cx,viewy+p[shapes-10].cy,viewz+p[shapes-10].cz , p[shapes-10].rx,p[shapes-10].ry,p[shapes-10].rz);
  for (f=shapes-9; f<shapes; f++) if (p[f].type>-1)
  {
    spinprojectile(f, 0,0,0, o[0].rsx,o[0].rsy,o[0].rsz,0);
    if (planets!=0) apiplanet(p[f].object,p[f].shape,viewx+(p[f].cx/1),viewy+(p[f].cy/1),viewz+(p[f].cz/1) , p[f].rx,p[f].ry,p[f].rz);
  }
  if(planets==2) dddInsertObject(light);
}

void  displaybriefing(void)
{
  int f;
  for (f=1; f<8; f++)
  {
//    apigameprint3(17+f*2,30,(150+(f*6)),ce[f].msg);
    apiniceprint4(21+f,35+f,36+f,37+f,30,(150+(f*6)),ce[f].msg);
  }
}

void  drawguiobjects(float rsx,float rsy,float rsz)
{
  int f;

  for (f=0; f<numguiobjects; f++) if (gui[f].type>-1)
  {
    spinguiobject(f, 0,0,0, rsx,rsy,rsz,0);
    spinguiobject(f, gui[f].cx,gui[f].cy,gui[f].cz, gui[f].rsx,gui[f].rsy,gui[f].rsz,0);
    apiguishape(DRAWFULL,gui[f].object,1,viewx+gui[f].cx,viewy+gui[f].cy,viewz+gui[f].cz , gui[f].rx,gui[f].ry,gui[f].rz);
  }
}

void drawdebrisfield(void)
{
  int f;
  if(ground>0) return;
  for (f=0; f<debris; f++)
  {
    spindebris(f, 0,0,0, o[0].rsx,o[0].rsy,o[0].rsz);
    spindebris(f, d[f].x,d[f].y,d[f].z, d[f].rsx,d[f].rsy,d[f].rsz);
    d[f].z-=o[0].speed*7;
    if(d[f].z<-1000 || d[f].z>1000)
    {
      if(d[f].z<-1000) d[f].z+=(2000+apirandom(1000));
      else d[f].z-=(2000+apirandom(1000));
      d[f].x=apirandom(1000)-500;
      d[f].y=apirandom(1000)-500;
      d[f].rsx=saferandom(10);
      d[f].rsy=saferandom(10);
      d[f].rsz=saferandom(10);
    }
    apiprojectile(DRW_SIMPLE,d[f].object,0,viewx+(d[f].x*5),viewy+(d[f].y*5),viewz+(d[f].z*5) , d[f].rx,d[f].ry,d[f].rz );
  }
}

void attached(int f)
{
  int g;
  if (attachedobjects!=OFF && o[f].thingys>0) for (g=0; g<o[f].thingys; g++)
  {
    if(o[f].thingytype[g]==1) dddRotateBy(o[f].thingy[g],0,300,0);
    else if(o[f].thingytype[g]==2) dddRotateBy(o[f].thingy[g],0,600,0);
    else if(o[f].thingytype[g]==3) dddRotateBy(o[f].thingy[g],300,0,0);
    else if(o[f].thingytype[g]==4) dddRotateBy(o[f].thingy[g],600,0,0);
    else if(o[f].thingytype[g]==11) dddRotateBy(o[f].thingy[g],0,0,10600);
    else if(o[f].thingytype[g]==12) dddRotateBy(o[f].thingy[g],0,0,-8400);
    else if(o[f].thingytype[g]==13) dddRotateBy(o[f].thingy[g],0,0,9400);
    else if(o[f].thingytype[g]>100 && o[f].thingytype[g]<200)
    {
      if(o[f].thingytype[g]==101) dddRotateBy(o[f].thingy[g],0,0,10600);
      if(o[f].thingytype[g]==102) dddRotateBy(o[f].thingy[g],0,0,-9400);
      if(o[f].thingytype[g]==103) dddRotateBy(o[f].thingy[g],0,0,8400);
      if(o[f].speed>=o[f].topspeed-1 && o[f].doing!=DIEING) dddSetShapeFlags(o[f].thingy[g],4);
      else if (o[f].speed<=1 || o[f].doing==DIEING) dddSetShapeFlags(o[f].thingy[g],0);
      else if(o[f].speed>o[f].topspeed/2) dddSetShapeFlags(o[f].thingy[g],3);
      else if(o[f].speed>o[f].topspeed/4) dddSetShapeFlags(o[f].thingy[g],2);
      else if(o[f].speed>1) dddSetShapeFlags(o[f].thingy[g],1);
    }
  }
}

void drawground(void)
{
  int f;
  float x,y,z,total;
  if(ground>0)
  {
    for(f=0;f<9;f++)
    {
      spinground(f, 0,0,0, o[0].rsx,o[0].rsy,o[0].rsz);
      gr[f].cz-=o[0].speed*velconst; // Move the ground
      if (o[0].doing==ENTERING_HYPERSPACE && o[0].frame1<0) gr[f].cz+=o[0].frame1*100;
    }
    apiplanet(gr[4].object,99,gr[4].cx,gr[4].cy,gr[4].cz , gr[4].rx,gr[4].ry,gr[4].rz);

    x=gr[4].cx; // Prepare to rotate a virtual ground so that it is flat;
    y=gr[4].cy; // Then, y = height, and x and z equal x and z distance
    z=gr[4].cz; // along the ground's own plane. ASDA Quality.
    rotatesummat(&x,&y,&z , -gr[4].rx/655,gr[4].ry/655,-gr[4].rz/655);
    if (z<-8000) for(f=0;f<9;f++) // Has it fucked off that way?
    {
      gr[f].cx+=gr[f].dx[0]*16;
      gr[f].cy+=gr[f].dy[0]*16;
      gr[f].cz+=gr[f].dz[0]*16;
    }
    if (z>8000) for(f=0;f<9;f++) // Has it fucked off this way?
    {
      gr[f].cx-=gr[f].dx[0]*16;
      gr[f].cy-=gr[f].dy[0]*16;
      gr[f].cz-=gr[f].dz[0]*16;
    }
    if (x<-8000) for(f=0;f<9;f++) // Has it fucked off sideways?
    {
      gr[f].cx+=gr[f].dx[2]*1.6;
      gr[f].cy+=gr[f].dy[2]*1.6;
      gr[f].cz+=gr[f].dz[2]*1.6;
    }
    if (x>8000) for(f=0;f<9;f++) // Has it fucked off sideways?
    {
      gr[f].cx-=gr[f].dx[2]*1.6;
      gr[f].cy-=gr[f].dy[2]*1.6;
      gr[f].cz-=gr[f].dz[2]*1.6;
    }
    // We keep the 9 normals for each non existant ground plate for
    // safety sake and average height calculations.
  }
  total=0;
  while(height>5000)
  {
    total+=0.01;
    for(f=0;f<9;f++)
    {
      gr[f].cx-=gr[4].dx[1]*0.01;
      gr[f].cy-=gr[4].dy[1]*0.01;
      gr[f].cz-=gr[4].dz[1]*0.01;
    }
    calculateheight(0);
  }
  if(total!=0)
  {
    for(f=1; f<ships; f++)
    {
      o[f].cx-=gr[4].dx[1]*total;
      o[f].cy-=gr[4].dy[1]*total;
      o[f].cz-=gr[4].dz[1]*total;
    }
    for(f=0; f<shapes-10; f++)
    {
      p[f].cx-=gr[4].dx[1]*total;
      p[f].cy-=gr[4].dy[1]*total;
      p[f].cz-=gr[4].dz[1]*total;
    }
  }
}
