home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / world.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-06-01  |  10.4 KB  |  346 lines

  1. // world.cpp: core map management stuff
  2.  
  3. #include "cube.h"
  4. #include "bot/bot.h"
  5.  
  6.  
  7. sqr *world = NULL;
  8. int sfactor, ssize, cubicsize, mipsize;
  9.  
  10. header hdr;
  11.  
  12. // main geometric mipmapping routine, recursively rebuild mipmaps within block b.
  13. // tries to produce cube out of 4 lower level mips as well as possible,
  14. // sets defer to 0 if mipped cube is a perfect mip, i.e. can be rendered at this
  15. // mip level indistinguishable from its constituent cubes (saves considerable
  16. // rendering time if this is possible).
  17.  
  18. void remip(block &b, int level)
  19. {
  20.     if(level>=SMALLEST_FACTOR) return;
  21.     int lighterr = getvar("lighterror")*3;
  22.     sqr *w = wmip[level];
  23.     sqr *v = wmip[level+1];
  24.     int ws = ssize>>level;
  25.     int vs = ssize>>(level+1);
  26.     block s = b;
  27.     if(s.x&1) { s.x--; s.xs++; }
  28.     if(s.y&1) { s.y--; s.ys++; }
  29.     s.xs = (s.xs+1)&~1;
  30.     s.ys = (s.ys+1)&~1;
  31.     for(int x = s.x; x<s.x+s.xs; x+=2) for(int y = s.y; y<s.y+s.ys; y+=2)
  32.     {
  33.         sqr *o[4];
  34.         o[0] = SWS(w,x,y,ws);                               // the 4 constituent cubes
  35.         o[1] = SWS(w,x+1,y,ws);
  36.         o[2] = SWS(w,x+1,y+1,ws);
  37.         o[3] = SWS(w,x,y+1,ws);
  38.         sqr *r = SWS(v,x/2,y/2,vs);                         // the target cube in the higher mip level
  39.         *r = *o[0];
  40.         uchar nums[MAXTYPE];
  41.         loopi(MAXTYPE) nums[i] = 0;
  42.         loopj(4) nums[o[j]->type]++;
  43.         r->type = SEMISOLID;                                // cube contains both solid and space, treated specially in the renderer
  44.         loopk(MAXTYPE) if(nums[k]==4) r->type = k;
  45.         if(!SOLID(r))
  46.         {
  47.             int floor = 127, ceil = -128, num = 0;
  48.             loopi(4) if(!SOLID(o[i]))
  49.             {
  50.                 num++;
  51.                 int fh = o[i]->floor;
  52.                 int ch = o[i]->ceil;
  53.                 if(r->type==SEMISOLID)
  54.                 {
  55.                     if(o[i]->type==FHF) fh -= o[i]->vdelta/4+2;     // crap hack, needed for rendering large mips next to hfs
  56.                     if(o[i]->type==CHF) ch += o[i]->vdelta/4+2;     // FIXME: needs to somehow take into account middle vertices on higher mips
  57.                 }
  58.                 if(fh<floor) floor = fh;  // take lowest floor and highest ceil, so we never have to see missing lower/upper from the side
  59.                 if(ch>ceil) ceil = ch;
  60.             }
  61.             r->floor = floor;
  62.             r->ceil = ceil;
  63.         }       
  64.         if(r->type==CORNER) goto mip;                       // special case: don't ever split even if textures etc are different
  65.         r->defer = 1;
  66.         if(SOLID(r))
  67.         {
  68.             loopi(3)
  69.             {
  70.                 if(o[i]->wtex!=o[3]->wtex) goto c;          // on an all solid cube, only thing that needs to be equal for a perfect mip is the wall texture
  71.             }
  72.         }
  73.         else
  74.         {
  75.             loopi(3)
  76.             {
  77.                 if(o[i]->type!=o[3]->type
  78.                 || o[i]->floor!=o[3]->floor
  79.                 || o[i]->ceil!=o[3]->ceil
  80.                 || o[i]->ftex!=o[3]->ftex
  81.                 || o[i]->ctex!=o[3]->ctex
  82.                 || abs(o[i+1]->r-o[0]->r)>lighterr          // perfect mip even if light is not exactly equal
  83.                 || abs(o[i+1]->g-o[0]->g)>lighterr
  84.                 || abs(o[i+1]->b-o[0]->b)>lighterr
  85.                 || o[i]->utex!=o[3]->utex
  86.                 || o[i]->wtex!=o[3]->wtex) goto c;
  87.             }
  88.             if(r->type==CHF || r->type==FHF)                // can make a perfect mip out of a hf if slopes lie on one line
  89.             {
  90.                 if(o[0]->vdelta-o[1]->vdelta != o[1]->vdelta-SWS(w,x+2,y,ws)->vdelta
  91.                 || o[0]->vdelta-o[2]->vdelta != o[2]->vdelta-SWS(w,x+2,y+2,ws)->vdelta
  92.                 || o[0]->vdelta-o[3]->vdelta != o[3]->vdelta-SWS(w,x,y+2,ws)->vdelta
  93.                 || o[3]->vdelta-o[2]->vdelta != o[2]->vdelta-SWS(w,x+2,y+1,ws)->vdelta
  94.                 || o[1]->vdelta-o[2]->vdelta != o[2]->vdelta-SWS(w,x+1,y+2,ws)->vdelta) goto c;
  95.             }
  96.         }
  97.         { loopi(4) if(o[i]->defer) goto c; }               // if any of the constituents is not perfect, then this one isn't either
  98.         mip:
  99.         r->defer = 0;
  100.         c:;
  101.     }
  102.     s.x  /= 2;
  103.     s.y  /= 2;
  104.     s.xs /= 2;
  105.     s.ys /= 2;
  106.     remip(s, level+1);
  107. }
  108.  
  109. void remipmore(block &b, int level)
  110. {
  111.     block bb = b;
  112.     if(bb.x>1) bb.x--;
  113.     if(bb.y>1) bb.y--;
  114.     if(bb.xs<ssize-3) bb.xs++;
  115.     if(bb.ys<ssize-3) bb.ys++;
  116.     remip(bb, level);
  117. }
  118.  
  119. int closestent()        // used for delent and edit mode ent display
  120. {
  121.     if(noteditmode()) return -1;
  122.     int best = -1;
  123.     float bdist = 99999;
  124.     loopv(ents)
  125.     {
  126.         entity &e = ents[i];
  127.         if(e.type==NOTUSED) continue;
  128.         vec v(e.x, e.y, e.z);
  129.         float dist = v.dist(camera1->o);
  130.         if(dist<bdist)
  131.         {
  132.             best = i;
  133.             bdist = dist;
  134.         }
  135.     }
  136.     return bdist==99999 ? -1 : best; 
  137. }
  138.  
  139. void entproperty(int prop, int amount)
  140. {
  141.     int e = closestent();
  142.     if(e<0) return;
  143.     switch(prop)
  144.     {
  145.         case 0: ents[e].attr1 += amount; break;
  146.         case 1: ents[e].attr2 += amount; break;
  147.         case 2: ents[e].attr3 += amount; break;
  148.         case 3: ents[e].attr4 += amount; break;
  149.     }
  150. }
  151.  
  152. hashtable<char *, enet_uint32> mapinfo, &resdata = mapinfo;
  153.  
  154. void delent()
  155. {
  156.     int e = closestent();
  157.     if(e<0) { conoutf("no more entities"); return; }
  158.     int t = ents[e].type;
  159.     conoutf("%s entity deleted", entnames[t]);
  160.     ents[e].type = NOTUSED;
  161.     addmsg(SV_EDITENT, "ri9", e, NOTUSED, 0, 0, 0, 0, 0, 0, 0);
  162.     if(t==LIGHT) calclight();
  163. }
  164.  
  165. int findtype(char *what)
  166. {
  167.     loopi(MAXENTTYPES) if(strcmp(what, entnames[i])==0) return i;
  168.     conoutf("unknown entity type \"%s\"", what);
  169.     return NOTUSED;
  170. }
  171.  
  172. entity *newentity(int x, int y, int z, char *what, int v1, int v2, int v3, int v4)
  173. {
  174.     int type = findtype(what);
  175.     persistent_entity e = { x, y, z, v1, type, v2, v3, v4 };
  176.     switch(type)
  177.     {
  178.         case LIGHT:
  179.             if(v1>64) v1 = 64;//if(v1>32) v1=32;
  180.             if(!v1) e.attr1 = 16;
  181.             if(!v2 && !v3 && !v4) e.attr2 = 255;          
  182.             break;
  183.             
  184.         case MAPMODEL:
  185.             e.attr4 = e.attr3;
  186.             e.attr3 = e.attr2;
  187.             e.attr2 = (uchar)e.attr1;
  188.         case PLAYERSTART:
  189.         case CTF_FLAG:
  190.             e.attr2 = v1;
  191.             e.attr1 = (int)camera1->yaw;
  192.             break;
  193.     }
  194.     addmsg(SV_EDITENT, "ri9", ents.length(), type, e.x, e.y, e.z, e.attr1, e.attr2, e.attr3, e.attr4);
  195.     ents.add(*((entity *)&e)); // unsafe!
  196.     if(type==LIGHT) calclight();
  197.     return &ents.last();
  198. }
  199.  
  200. void clearents(char *name)
  201. {  
  202.     int type = findtype(name);
  203.     if(noteditmode() || multiplayer()) return;
  204.     loopv(ents)
  205.     {
  206.         entity &e = ents[i];
  207.         if(e.type==type) e.type = NOTUSED;
  208.     }
  209.     if(type==LIGHT) calclight();
  210. }
  211.  
  212. COMMAND(clearents, ARG_1STR);
  213.  
  214. void scalecomp(uchar &c, int intens)
  215. {
  216.     int n = c*intens/100;
  217.     if(n>255) n = 255;
  218.     c = n;
  219. }
  220.  
  221. void scalelights(int f, int intens)
  222. {
  223.     loopv(ents)
  224.     {
  225.         entity &e = ents[i];
  226.         if(e.type!=LIGHT) continue;
  227.         e.attr1 = e.attr1*f/100;
  228.         if(e.attr1<2) e.attr1 = 2;
  229.         if(e.attr1>32) e.attr1 = 32;
  230.         if(intens)
  231.         {
  232.             scalecomp(e.attr2, intens);
  233.             scalecomp(e.attr3, intens);
  234.             scalecomp(e.attr4, intens);
  235.         }
  236.     }
  237.     calclight();
  238. }
  239.  
  240. COMMAND(scalelights, ARG_2INT);
  241.  
  242. int findentity(int type, int index)
  243. {
  244.     for(int i = index; i<ents.length(); i++) if(ents[i].type==type) return i;
  245.     loopj(index) if(ents[j].type==type) return j;
  246.     return -1;
  247. }
  248.  
  249. int findentity(int type, int index, uchar attr2)
  250. {
  251.     for(int i = index; i<ents.length(); i++) if(ents[i].type==type && ents[i].attr2==attr2) return i;
  252.     loopj(index) if(ents[j].type==type && ents[j].attr2==attr2) return j;
  253.     return -1;
  254. }
  255.  
  256. sqr *wmip[LARGEST_FACTOR*2];
  257.  
  258. void setupworld(int factor)
  259. {
  260.     ssize = 1<<(sfactor = factor);
  261.     cubicsize = ssize*ssize;
  262.     mipsize = cubicsize*134/100;
  263.     sqr *w = world = new sqr[mipsize];
  264.     memset(world, 0, mipsize*sizeof(sqr));
  265.     loopi(LARGEST_FACTOR*2) { wmip[i] = w; w += cubicsize>>(i*2); }
  266. }
  267.  
  268. void empty_world(int factor, bool force)    // main empty world creation routine, if passed factor -1 will enlarge old world by 1
  269. {
  270.     if(!force && noteditmode()) return; 
  271.     cleardlights();
  272.     pruneundos();
  273.     sqr *oldworld = world;
  274.     bool copy = false;
  275.     if(oldworld && factor<0) { factor = sfactor+1; copy = true; }
  276.     if(factor<SMALLEST_FACTOR) factor = SMALLEST_FACTOR;
  277.     if(factor>LARGEST_FACTOR) factor = LARGEST_FACTOR;
  278.     setupworld(factor);
  279.     
  280.     loop(x,ssize) loop(y,ssize)
  281.     {
  282.         sqr *s = S(x,y);
  283.         s->r = s->g = s->b = 150;
  284.         s->ftex = DEFAULT_FLOOR;
  285.         s->ctex = DEFAULT_CEIL;
  286.         s->wtex = s->utex = DEFAULT_WALL;
  287.         s->type = SOLID;
  288.         s->floor = 0;
  289.         s->ceil = 16;
  290.         s->vdelta = 0;
  291.         s->defer = 0;
  292.     }
  293.     
  294.     strncpy(hdr.head, "ACMP", 4);
  295.     hdr.version = MAPVERSION;
  296.     hdr.headersize = sizeof(header);
  297.     hdr.sfactor = sfactor;
  298.  
  299.     if(copy)
  300.     {
  301.         loop(x,ssize/2) loop(y,ssize/2)
  302.         {
  303.             *S(x+ssize/4, y+ssize/4) = *SWS(oldworld, x, y, ssize/2);
  304.         }
  305.         loopv(ents)
  306.         {
  307.             ents[i].x += ssize/4;
  308.             ents[i].y += ssize/4;
  309.         }
  310.     }
  311.     else
  312.     {
  313.         s_strncpy(hdr.maptitle, "Untitled Map by Unknown", 128);
  314.         hdr.waterlevel = -100000;
  315.         setwatercolor();
  316.         loopi(sizeof(hdr.reserved)/sizeof(hdr.reserved[0])) hdr.reserved[i] = 0;
  317.         loopk(3) loopi(256) hdr.texlists[k][i] = i;
  318.         ents.setsize(0);
  319.         block b = { 8, 8, ssize-16, ssize-16 }; 
  320.         edittypexy(SPACE, b);
  321.     }
  322.     
  323.     calclight();
  324.     if(factor>=0) startmap("");
  325.     if(oldworld)
  326.     {
  327.         delete[] oldworld;
  328.         if(factor>=0)
  329.         {
  330.             toggleedit();
  331.             execfile("config/default_map_settings.cfg");
  332.             execute("fullbright 1");
  333.         }
  334.     }
  335. }
  336.  
  337. void mapenlarge()  { empty_world(-1, false); }
  338. void newmap(int i) { empty_world(i, false); }
  339.  
  340. COMMAND(mapenlarge, ARG_NONE);
  341. COMMAND(newmap, ARG_1INT);
  342. COMMANDN(recalc, calclight, ARG_NONE);
  343. COMMAND(delent, ARG_NONE);
  344. COMMAND(entproperty, ARG_2INT);
  345.  
  346.