Guest User

Assault Cube Map Editor Diff (1.2.0.2)

a guest
Jan 11th, 2021
8
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --- audiomanager.cpp    Tue Oct 22 13:57:19 2013
  2. +++ audiomanager.cpp    Wed Apr 02 17:25:06 2014
  3. @@ -554,7 +554,7 @@
  4. // main audio update routine
  5.  
  6. void audiomanager::updateaudio()
  7. -{
  8. +{
  9.      if(nosound) return;
  10.  
  11.      alcSuspendContext(context); // don't process sounds while we mess around
  12. @@ -606,7 +606,7 @@
  13.          {
  14.              entity &e = ents[i];
  15.              vec o(e.x, e.y, e.z);
  16. -            if(e.type!=SOUND) continue;
  17. +            if(e.type!=SOUND) continue;
  18.  
  19.              int sound = e.attr1;
  20.              int radius = e.attr2;
  21. --- clientgame.cpp    Tue Oct 22 13:57:19 2013
  22. +++ clientgame.cpp    Fri Apr 11 14:43:34 2014
  23. @@ -1116,10 +1116,13 @@
  24. COMMAND(showmapstats, "");
  25.  
  26. VARP(showmodedescriptions, 0, 1, 1);
  27. -extern bool canceldownloads;
  28. +extern bool canceldownloads;
  29. +
  30. +extern bool lockselent;
  31.  
  32. void startmap(const char *name, bool reset)   // called just after a map load
  33. -{
  34. +{
  35. +    lockselent = false;
  36.      canceldownloads = false;
  37.      copystring(clientmap, name);
  38.      sendmapidenttoserver = true;
  39. --- cube.h    Sat Nov 09 17:56:31 2013
  40. +++ cube.h    Mon May 19 23:38:03 2014
  41. @@ -43,7 +43,8 @@
  42. extern vector<int> eh_ents;             // edithide entities
  43. extern vec worldpos, camup, camright, camdir; // current target of the crosshair in the world
  44. extern int lastmillis, totalmillis, nextmillis; // last time
  45. -extern int curtime;                     // current frame time
  46. +extern int curtime;                     // current frame time
  47. +extern int globalfps;
  48. extern int interm;
  49. extern int gamemode, nextmode;
  50. extern int gamespeed;
  51. --- editing.cpp    Tue Oct 22 13:57:16 2013
  52. +++ editing.cpp    Sat Jun 07 00:41:10 2014
  53. @@ -3,12 +3,20 @@
  54. #include "cube.h"
  55.  
  56. bool editmode = false;
  57. +
  58. +int globalfps = 0;
  59.  
  60. // the current selections, used by almost all editing commands
  61. // invariant: all code assumes that these are kept inside MINBORD distance of the edge of the map
  62. // => selections are checked when they are made or when the world is reloaded
  63.  
  64. -vector<block> sels;
  65. +VAR(cleanedit, 0, 0, 1);
  66. +COMMANDF(togglecleanedit, "", () {cleanedit = !cleanedit;});
  67. +
  68. +COMMANDF(clearrecenttex, "", () {loopk(3) loopi(256) hdr.texlists[k][i] = i;});
  69. +
  70. +vector<block> sels;
  71. +vector<block> s_sels; //saved selections
  72.  
  73. #define loopselxy(sel, b) { makeundo(sel); loop(x,(sel).xs) loop(y,(sel).ys) { sqr *s = S((sel).x+x, (sel).y+y); b; } remip(sel); }
  74. #define loopselsxy(b) { loopv(sels) loopselxy(sels[i], b); }
  75. @@ -70,6 +78,20 @@
  76.      }
  77.      return !editmode;
  78. }
  79. +
  80. +void savesel()
  81. +{
  82. +    s_sels = sels;
  83. +}
  84. +
  85. +void reselect()
  86. +{
  87. +    sels = s_sels;
  88. +}
  89. +
  90. +COMMAND (savesel, "");
  91. +COMMAND (reselect, "");
  92. +
  93.  
  94. inline bool selset()
  95. {
  96. @@ -81,6 +103,48 @@
  97.      if(!selset()) conoutf("no selection");
  98.      return !selset();
  99. }
  100. +
  101. +const char *entcolor(int index) // helper function for editinfo()
  102. +{
  103. +    entity &e = ents[index];
  104. +
  105. +    switch(e.type)
  106. +    {
  107. +        case 2: // playerstart
  108. +        if (e.attr2 == 0) // CLA
  109. +        return "3";
  110. +
  111. +        else if (e.attr2 == 1) // RVSF
  112. +        return "1";
  113. +
  114. +        else return "J"; // FFA
  115. +
  116. +        case 3: case 4: case 5: case 9: return "9"; // pistol clip, ammobox, grenade, akimbo
  117. +        case 6: case 7: case 8: return "H"; // health pack, helmet, armor
  118. +        case 10: return "T"; // mapmodel
  119. +
  120. +        case 12: return "M"; // ladder
  121. +
  122. +        case 13: // ctf-flag
  123. +        if (e.attr2 == 0) // CLA
  124. +        return "3";
  125. +
  126. +        else if (e.attr2 == 1) // RVSF
  127. +        return "1";
  128. +        break;
  129. +
  130. +        case 14: return "P"; // sound
  131. +
  132. +        case 15: return "2"; // clip
  133. +        case 16: return "X"; // plclip
  134. +
  135. +        default:
  136. +        return "5"; // white
  137. +    }
  138. +    return "5"; // white
  139. +}
  140. +
  141. +extern bool lockselent;
  142.  
  143. char *editinfo()
  144. {
  145. @@ -88,14 +152,43 @@
  146.      if(!editmode) return NULL;
  147.      int e = closestent();
  148.      if(e<0) return NULL;
  149. -    entity &c = ents[e];
  150. +    entity &c = ents[e];
  151. +
  152.      string selinfo = "no selection";
  153. -    if(selset()) formatstring(selinfo)("selection = (%d, %d)", (sels.last()).xs, (sels.last()).ys);
  154. -    formatstring(info)("closest entity = %s (%d, %d, %d, %d), %s", entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4, selinfo);
  155. +    if(selset()) formatstring(selinfo)("selection = (%d, %d)", (sels.last()).xs, (sels.last()).ys);
  156. +
  157. +    string fileinfo = "";
  158. +    switch (c.type)
  159. +    {
  160. +        case SOUND:
  161. +        if (mapsounds.inrange(c.attr1))
  162. +        formatstring(fileinfo)("\n%s", mapsounds[c.attr1].buf->name);
  163. +        else
  164. +        formatstring(fileinfo)("\n\f7unregistered sound\f5");
  165. +        break;
  166. +
  167. +        case MAPMODEL:
  168. +        {
  169. +            mapmodelinfo &mmi = getmminfo(c.attr2);
  170. +            if (&mmi)
  171. +            formatstring(fileinfo)("\n%s", mmi.name);
  172. +            else
  173. +            formatstring(fileinfo)("\n\f7unregistered mapmodel\f5");
  174. +        }
  175. +        break;
  176. +
  177. +        default:
  178. +        break;
  179. +    }
  180. +
  181. +    if (!lockselent)
  182. +    formatstring(info)("closest entity:\n\f%s%s\f5 (%d, %d, %d, %d), %s %s", entcolor(e), entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4, selinfo, fileinfo);
  183. +    else
  184. +    formatstring(info)("selected entity:\n\f%s%s\f5 (%d, %d, %d, %d), %s %s", entcolor(e), entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4, selinfo, fileinfo);
  185. +
  186.      return info;
  187. }
  188.  
  189. -
  190. #define EDITSEL   if(noteditmode("EDITSEL") || noselection()) return
  191. #define EDITSELMP if(noteditmode("EDITSELMP") || noselection() || multiplayer()) return
  192. #define EDITMP    if(noteditmode("EDITMP") || multiplayer()) return
  193. @@ -150,87 +243,182 @@
  194.  
  195. // VC8 optimizer screws up rendering somehow if this is an actual function
  196. #define sheight(s,t,z) (!flrceil ? (s->type==FHF ? s->floor-t->vdelta/4.0f : (float)s->floor) : (s->type==CHF ? s->ceil+t->vdelta/4.0f : (float)s->ceil))
  197. -
  198. -void cursorupdate()                                     // called every frame from hud
  199. -{
  200. -    flrceil = ((int)(camera1->pitch>=0))*2;
  201. -    int cyaw = ((int) camera1->yaw) % 180;
  202. -    editaxis = editmode ? (fabs(camera1->pitch) > 65 ? 13 : (cyaw < 45 || cyaw > 135 ? 12 : 11)) : 0;
  203. -
  204. -    volatile float x = worldpos.x;                      // volatile needed to prevent msvc7 optimizer bug?
  205. -    volatile float y = worldpos.y;
  206. -    volatile float z = worldpos.z;
  207. -
  208. -    cx = (int)x;
  209. -    cy = (int)y;
  210. -
  211. -    if(OUTBORD(cx, cy)) return;
  212. -    sqr *s = S(cx,cy);
  213. -
  214. -    if(fabs(sheight(s,s,z)-z)>1)                        // selected wall
  215. -    {
  216. -        x += x>camera1->o.x ? 0.5f : -0.5f;             // find right wall cube
  217. -        y += y>camera1->o.y ? 0.5f : -0.5f;
  218. -
  219. -        cx = (int)x;
  220. -        cy = (int)y;
  221. -
  222. -        if(OUTBORD(cx, cy)) return;
  223. -    }
  224. -
  225. -    if(dragging) { makesel(false); };
  226. -
  227. -    const int GRIDSIZE = 5;
  228. -    const float GRIDW = 0.5f;
  229. -    const float GRID8 = 2.0f;
  230. -    const float GRIDS = 2.0f;
  231. -    const int GRIDM = 0x7;
  232. -
  233. -    // render editing grid
  234. -
  235. -    if(showgrid)
  236. -    {
  237. -        for(int ix = cx-GRIDSIZE; ix<=cx+GRIDSIZE; ix++) for(int iy = cy-GRIDSIZE; iy<=cy+GRIDSIZE; iy++)
  238. -        {
  239. -
  240. -            if(OUTBORD(ix, iy)) continue;
  241. -            sqr *s = S(ix,iy);
  242. -            if(SOLID(s)) continue;
  243. -            float h1 = sheight(s, s, z);
  244. -            float h2 = sheight(s, SWS(s,1,0,sfactor), z);
  245. -            float h3 = sheight(s, SWS(s,1,1,sfactor), z);
  246. -            float h4 = sheight(s, SWS(s,0,1,sfactor), z);
  247. -            if(s->tag) linestyle(GRIDW, 0xFF, 0x40, 0x40);
  248. -            else if(s->type==FHF || s->type==CHF) linestyle(GRIDW, 0x80, 0xFF, 0x80);
  249. -            else linestyle(GRIDW, 0x80, 0x80, 0x80);
  250. -            block b = { ix, iy, 1, 1 };
  251. -            box(b, h1, h2, h3, h4);
  252. -            linestyle(GRID8, 0x40, 0x40, 0xFF);
  253. -            if(!(ix&GRIDM))   line(ix,   iy,   h1, ix,   iy+1, h4);
  254. -            if(!((ix+1)&GRIDM)) line(ix+1, iy,   h2, ix+1, iy+1, h3);
  255. -            if(!(iy&GRIDM))   line(ix,   iy,   h1, ix+1, iy,   h2);
  256. -            if(!((iy+1)&GRIDM)) line(ix,   iy+1, h4, ix+1, iy+1, h3);
  257. -        }
  258. -
  259. -        if(!SOLID(s))
  260. -        {
  261. -            float ih = sheight(s, s, z);
  262. -            linestyle(GRIDS, 0xFF, 0xFF, 0xFF);
  263. -            block b = { cx, cy, 1, 1 };
  264. -            box(b, ih, sheight(s, SWS(s,1,0,sfactor), z), sheight(s, SWS(s,1,1,sfactor), z), sheight(s, SWS(s,0,1,sfactor), z));
  265. -            linestyle(GRIDS, 0xFF, 0x00, 0x00);
  266. -            dot(cx, cy, ih);
  267. -            ch = (int)ih;
  268. -        }
  269. -    }
  270. -
  271. -    if(selset())
  272. -    {
  273. -        linestyle(GRIDS, 0xFF, 0x40, 0x40);
  274. -        loopv(sels) box(sels[i], (float)sels[i].h, (float)sels[i].h, (float)sels[i].h, (float)sels[i].h);
  275. -    }
  276. -
  277. -    glLineWidth(1);
  278. +
  279. +int gridalpha = 255;
  280. +int delay = 128;
  281. +float old_p, old_y;
  282. +
  283. +void cursorupdate()                                     // called every frame from hud
  284. +{
  285. +    if (old_p != camera1->pitch || old_y != camera1->yaw)
  286. +    {gridalpha = 255; delay = 128;}
  287. +    else
  288. +    {
  289. +        delay -= ((255 / globalfps) + 1 );
  290. +        if (delay < 0) delay = 0;
  291. +
  292. +        if (!delay)
  293. +        gridalpha -= ((gridalpha * 3 / globalfps) + 1 );
  294. +
  295. +        if (gridalpha < 0)
  296. +        gridalpha = 0;
  297. +    }
  298. +
  299. +    if (!gridalpha)
  300. +    return;
  301. +
  302. +    old_p = camera1->pitch;
  303. +    old_y = camera1->yaw;
  304. +
  305. +    flrceil = ((int)(camera1->pitch>=0))*2;
  306. +    int cyaw = ((int) camera1->yaw) % 180;
  307. +    editaxis = editmode ? (fabs(camera1->pitch) > 65 ? 13 : (cyaw < 45 || cyaw > 135 ? 12 : 11)) : 0;
  308. +
  309. +    volatile float x = worldpos.x;                      // volatile needed to prevent msvc7 optimizer bug?
  310. +    volatile float y = worldpos.y;
  311. +    volatile float z = worldpos.z;
  312. +
  313. +    cx = (int)x;
  314. +    cy = (int)y;
  315. +
  316. +    if (OUTBORD(cx, cy)) return;
  317. +    sqr *s = S(cx,cy);
  318. +
  319. +    if(fabs(sheight(s,s,z)-z)>1)                        // selected wall
  320. +    {
  321. +        x += x>camera1->o.x ? 0.5f : -0.5f;             // find right wall cube
  322. +        y += y>camera1->o.y ? 0.5f : -0.5f;
  323. +
  324. +        cx = (int)x;
  325. +        cy = (int)y;
  326. +
  327. +        if(OUTBORD(cx, cy)) return;
  328. +    }
  329. +
  330. +    if(dragging) { makesel(false); };
  331. +
  332. +    const int GRIDSIZE = 5;
  333. +    const float GRIDW = 0.5f;
  334. +    const float GRID8 = 2.0f;
  335. +    const float GRIDS = 2.0f;
  336. +    const int GRIDM = 0x7;
  337. +
  338. +    // render editing grid
  339. +
  340. +    glEnable(GL_BLEND);
  341. +    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  342. +
  343. +    for(int ix = cx-GRIDSIZE; ix<=cx+GRIDSIZE; ix++) for(int iy = cy-GRIDSIZE; iy<=cy+GRIDSIZE; iy++)
  344. +    {
  345. +        if(OUTBORD(ix, iy)) continue;
  346. +        sqr *s = S(ix,iy);
  347. +
  348. +        //if(SOLID(s)) continue;
  349. +
  350. +        float h1 = sheight(s, s, z);
  351. +        float h2 = sheight(s, SWS(s,1,0,sfactor), z);
  352. +        float h3 = sheight(s, SWS(s,1,1,sfactor), z);
  353. +        float h4 = sheight(s, SWS(s,0,1,sfactor), z);
  354. +
  355. +        /** "Tag" cube style **/
  356. +
  357. +        if(s->tag)
  358. +        {
  359. +            glLineWidth(GRIDW);
  360. +            glColor4ub(0x40, 0x40, 0xFF, (unsigned char)gridalpha);
  361. +        }
  362. +
  363. +        /** Heightfield Style **/
  364. +
  365. +        else if(s->type==FHF || s->type==CHF)
  366. +        {
  367. +            glLineWidth(GRIDW);
  368. +            glColor4ub(0x80, 0xFF, 0x80, (unsigned char)gridalpha); //green
  369. +        }
  370. +
  371. +        /** Solid cube style **/
  372. +
  373. +        else if(SOLID(s))
  374. +        {
  375. +            glLineWidth(GRID8);
  376. +            glColor4ub(0xAB, 0x40, 0xFE, (unsigned char)gridalpha); //purple
  377. +        }
  378. +
  379. +        /** Normal cube style **/
  380. +
  381. +        else
  382. +        {
  383. +            glLineWidth(GRIDW);
  384. +            glColor4ub(0x80, 0x80, 0x80, (unsigned char)gridalpha); //grey
  385. +        }
  386. +
  387. +        /** Actually drawing the grid **/
  388. +
  389. +        block b = { ix, iy, 1, 1 }; //set destination coordinates to draw to
  390. +        box(b, h1, h2, h3, h4); //draw
  391. +
  392. +        /** The repeating 8 x 8 grid **/
  393. +
  394. +        /* Choosing color **/
  395. +
  396. +        int temp = 255 - ((255-gridalpha)*3/2); //the thicker blue appears more opaque than other lines
  397. +        if (temp < 0) temp = 0;
  398. +
  399. +        glLineWidth(GRID8);
  400. +        glColor4ub(0x40, 0x40, 0xFF, (unsigned char)temp); //blue
  401. +
  402. +        /* Drawing lines on this grid */
  403. +
  404. +        if(!(ix&GRIDM))
  405. +        line(ix, iy, h1, ix, iy+1, h4);
  406. +
  407. +        if(!((ix+1)&GRIDM))
  408. +        line(ix+1, iy, h2, ix+1, iy+1, h3);
  409. +
  410. +        if(!(iy&GRIDM))
  411. +        line(ix, iy, h1, ix+1, iy, h2);
  412. +
  413. +        if(!((iy+1)&GRIDM))
  414. +        line(ix, iy+1, h4, ix+1, iy+1, h3);
  415. +    }
  416. +
  417. +    /** Draw white square around cube cursor is over **/
  418. +
  419. +
  420. +    float ih = sheight(s, s, z);
  421. +    {
  422. +        glLineWidth(GRIDS);
  423. +        glColor4ub(0xFF, 0xFF, 0xFF, (unsigned char)gridalpha); //white
  424. +    }
  425. +
  426. +    block b = { cx, cy, 1, 1 };
  427. +    box(b, ih, sheight(s, SWS(s,1,0,sfactor), z), sheight(s, SWS(s,1,1,sfactor), z), sheight(s, SWS(s,0,1,sfactor), z));
  428. +
  429. +    /** And the orienting little square in the corner **/
  430. +
  431. +    glLineWidth(GRIDS);
  432. +    glColor4ub(0xFF, 0x00, 0x00, (unsigned char)gridalpha); //red
  433. +    dot(cx, cy, ih);
  434. +
  435. +    ch = (int)ih; //updates height of selection box (the red boxes) to the correct height
  436. +
  437. +    /** Draw selection(s) **/
  438. +
  439. +    if(selset())
  440. +    {
  441. +        /* Choosing color */
  442. +
  443. +        glLineWidth(GRIDS);
  444. +        glColor4ub(0xFF, 0x40, 0x40, (unsigned char)gridalpha); //red
  445. +
  446. +        /* Drawing */
  447. +
  448. +        loopv(sels) //for each selection
  449. +        box(sels[i], (float)sels[i].h, (float)sels[i].h, (float)sels[i].h, (float)sels[i].h);
  450. +    }
  451. +
  452. +    glDisable(GL_BLEND);
  453. +    glLineWidth(1);
  454. }
  455.  
  456. vector<block *> undos;                                  // unlimited undo
  457. @@ -308,6 +496,44 @@
  458.          remipmore(sel);
  459.      }
  460. }
  461. +
  462. +
  463. +void paste_half()
  464. +{
  465. +    if(noteditmode("EDITSEL") || noselection()) return;
  466. +
  467. +    if(!copybuffers.length()) { conoutf("nothing to paste"); return; }
  468. +
  469. +    loopv(sels)
  470. +    {
  471. +        block &sel = sels[i];
  472. +        int selx = sel.x;
  473. +        int sely = sel.y;
  474. +
  475. +        loopvj(copybuffers)
  476. +        {
  477. +            block *copyblock = copybuffers[j];
  478. +            int dx = copyblock->x - copybuffers[0]->x, dy = copyblock->y - copybuffers[0]->y;
  479. +
  480. +            sel.xs = copyblock->xs;
  481. +            sel.ys = copyblock->ys;
  482. +            sel.x = selx + dx;
  483. +            sel.y = sely + dy;
  484. +
  485. +            if(!correctsel(sel) || sel.xs!=copyblock->xs || sel.ys!=copyblock->ys) { conoutf("incorrect selection"); return; }
  486. +            makeundo(sel);
  487. +
  488. +            if (flrceil == 0)
  489. +            halfblockpaste(*copyblock, sel.x, sel.y, true);
  490. +            else
  491. +            halfblockpaste(*copyblock, sel.x, sel.y, false);
  492. +        }
  493. +
  494. +        remipmore(sel);
  495. +    }
  496. +}
  497. +
  498. +COMMAND(paste_half, "");
  499.  
  500. // Count the walls of type "type" contained in the current selection
  501. void countwalls(int *type)
  502. @@ -338,6 +564,46 @@
  503.          }
  504.      }
  505. }
  506. +
  507. +int getcurtex(const char* pos, const char* x, const char* y); //prototype
  508. +
  509. +void tex2front(const char* pos)
  510. +{
  511. +    if (noselection())
  512. +    return;
  513. +
  514. +    int t = -1; //type (position)
  515. +
  516. +    if (strcmp(pos, "FLOOR") == 0) t = 0;
  517. +    else if (strcmp(pos, "WALL") == 0) t = 1;
  518. +    else if (strcmp(pos, "UPWALL") == 0) t = 3;
  519. +    else if (strcmp(pos, "CEIL") == 0) t = 2;
  520. +    else
  521. +    {
  522. +        conoutf("\f9ERROR: \f5invalid position argument");
  523. +        return;
  524. +    }
  525. +
  526. +    if (t == 3) t = 1; //walls
  527. +
  528. +    int key = getcurtex(pos, "", "");
  529. +    //conoutf("Key is texture slot %i", key);
  530. +    //conoutf("Searching edit texture lists for match...");
  531. +
  532. +    loopi(255)
  533. +    {
  534. +        if (hdr.texlists[t][i] == key)
  535. +        {
  536. +            //conoutf("Match found in position: %i", i);
  537. +            curedittex[t] = i;
  538. +            break;
  539. +        }
  540. +    }
  541. +
  542. +    tofronttex();
  543. +}
  544. +
  545. +COMMAND (tex2front, "s");
  546.  
  547. void editdrag(bool isdown)
  548. {
  549. @@ -454,6 +720,1002 @@
  550.          addmsg(SV_EDITT, "ri6", sels[i].x, sels[i].y, sels[i].xs, sels[i].ys, type, t);
  551.      }
  552. }
  553. +
  554. +int expandsel(int s) //makes all selections collections of 1 x 1 selections
  555. +{
  556. +    int count = 0; //number of cubes in selections to remove
  557. +
  558. +    int stop = sels.length();
  559. +    int removed = 0;
  560. +
  561. +    for (int i = 0; i < stop; i++)
  562. +    {
  563. +        for (int y = sels[i].y; y < sels[i].y + sels[i].ys; y++) //y loop
  564. +        for (int x = sels[i].x; x < sels[i].x + sels[i].xs; x++) //x loop
  565. +        {
  566. +            addselection(x, y, 1, 1, sels[i].h);
  567. +
  568. +            if (i >= stop - s) //selections to remove
  569. +            count++;
  570. +        }
  571. +
  572. +        sels.remove(i);
  573. +        i--;
  574. +        stop--;
  575. +        removed++;
  576. +    }
  577. +
  578. +
  579. +    return count;
  580. +}
  581. +
  582. +void compress_sel(int s) //combines adjacent selections (1 x 1 selections only)
  583. +{
  584. +    EDITSEL;
  585. +
  586. +    int min_x = 0;
  587. +    int min_y = 0;
  588. +
  589. +    int max_x = 0;
  590. +    int max_y = 0;
  591. +    int max_h = 0;
  592. +
  593. +    int x;
  594. +    int y;
  595. +    int h;
  596. +
  597. +    /** Initialize selections map **/
  598. +
  599. +    loopv(sels)
  600. +    {
  601. +        if (i == 0) //initialize bounds
  602. +        {
  603. +            min_x = sels[i].x + sels[i].xs;
  604. +            max_x = sels[i].x + sels[i].xs;
  605. +            min_y = sels[i].y + sels[i].ys;
  606. +            max_y = sels[i].y + sels[i].ys;
  607. +            max_h = sels[i].h;
  608. +        }
  609. +
  610. +        x = sels[i].x + sels[i].xs;
  611. +        y = sels[i].y + sels[i].ys;
  612. +        h = sels[i].h;
  613. +
  614. +        if (x < min_x) min_x = x;
  615. +
  616. +        if (x > max_x) max_x = x;
  617. +
  618. +        if (y < min_y) min_y = y;
  619. +
  620. +        if (y > max_y) max_y = y;
  621. +
  622. +        if (h > max_h) max_h = h;
  623. +    }
  624. +
  625. +    bool cubemap [2 + (max_y - min_y)][2 + (max_x - min_x)];
  626. +    memset(cubemap, false, sizeof(cubemap));
  627. +
  628. +    for(int i = 0; i<sels.length(); i++)
  629. +    {
  630. +        if (i < sels.length()-s)
  631. +        cubemap[sels[i].y + sels[i].ys - min_y] [sels[i].x + sels[i].xs - min_x] = true;
  632. +        else
  633. +        cubemap[sels[i].y + sels[i].ys - min_y] [sels[i].x + sels[i].xs - min_x] = false;
  634. +    }
  635. +
  636. +    /** reselect rows of cubes according to map **/
  637. +
  638. +    resetselections();
  639. +
  640. +    int slice_start; //first cube in a horizontal selection slice
  641. +
  642. +    for (y = 0; y < (max_y - min_y) + 1; y++)
  643. +    {
  644. +        slice_start = -1;
  645. +
  646. +        for (x = 0; x < (max_x - min_x) + 1; x++)
  647. +        {
  648. +            if (cubemap[y][x])
  649. +            {
  650. +                if (slice_start < 0)
  651. +                slice_start = x;
  652. +            }
  653. +            else
  654. +            {
  655. +                if (slice_start > -1)
  656. +                addselection(min_x + slice_start - 1, min_y + y - 1, x - slice_start, 1, max_h);
  657. +
  658. +                slice_start = -1;
  659. +                continue;
  660. +            }
  661. +
  662. +            if ((x + 1 >= (max_x - min_x) + 1) && slice_start > -1)
  663. +            addselection(min_x + slice_start - 1, min_y + y - 1, x - slice_start + 1, 1, max_h);
  664. +        }
  665. +    }
  666. +
  667. +    /** combine rows of equal length vertically adjacent to each other **/
  668. +
  669. +    int y2;
  670. +
  671. +    loopv (sels) //i loop
  672. +    loopvj (sels) //j loop
  673. +    {
  674. +        if (sels[i].x == sels[j].x) //same x coordinate
  675. +        if (sels[i].y == sels[j].y + sels[j].ys || sels[j].y == sels[i].y + sels[i].ys) //vertically adjacent
  676. +        if (sels[i].xs == sels[j].xs) //same length
  677. +        {
  678. +            min_y = sels[i].y;
  679. +            max_y = sels[i].y + sels[i].ys;
  680. +            max_h = sels[i].h;
  681. +
  682. +            y = sels[j].y;
  683. +            y2 = sels[j].y + sels[j].ys;
  684. +            h = sels[j].h;
  685. +
  686. +            if (y < min_y) min_y = y;
  687. +            if (y > max_y) max_y = y;
  688. +            if (y2 < min_y) min_y = y2;
  689. +            if (y2 > max_y) max_y = y2;
  690. +            if (h > max_h) max_h = h;
  691. +
  692. +            addselection(sels[i].x, min_y, sels[i].xs, max_y - min_y, max_h);
  693. +
  694. +            sels.remove(i);
  695. +
  696. +            if (i < j)  //if deleting i offset j
  697. +            sels.remove(j - 1);
  698. +            else
  699. +            sels.remove(j);
  700. +
  701. +            i = 0;
  702. +            break; //exit this j loop, go to next j loop, of i loop
  703. +        }
  704. +    }
  705. +}
  706. +
  707. +void fixselh ()
  708. +{
  709. +    bool fc;
  710. +
  711. +    if (flrceil == 0) fc = false; //floor
  712. +    else fc = true;
  713. +
  714. +    sqr *s1;
  715. +    sqr *s2;
  716. +
  717. +    loopv (sels)
  718. +    {
  719. +        s1 = S(sels[i].x, sels[i].y);
  720. +        s2 = S(sels[i].x + sels[i].xs - 1, sels[i].y + sels[i].ys - 1);
  721. +
  722. +        if(!fc) //finding max floor height
  723. +        {
  724. +            if (s1->floor > s2->floor)
  725. +            sels[i].h = s1->floor;
  726. +            else
  727. +            sels[i].h = s2->floor;
  728. +        }
  729. +        else //finding max ceiling height
  730. +        {
  731. +            if (s1->ceil > s2->ceil)
  732. +            sels[i].h = s1->ceil;
  733. +            else
  734. +            sels[i].h = s2->ceil;
  735. +        }
  736. +    }
  737. +}
  738. +
  739. +/** expand selections and select only selections matching argument keys **/
  740. +
  741. +void filter_sel(const char* type, char* v1, char* v2, char* v3, char* v4, char* v5, char* v6, char* v7)
  742. +{
  743. +    EDITSEL;
  744. +
  745. +    /** Process filter type **/
  746. +
  747. +    int filter_type = 0;
  748. +
  749. +    if (strcmp(type, "FLOOR_T") == 0) filter_type = 1;
  750. +    if (strcmp(type, "WALL_T") == 0) filter_type = 2;
  751. +    if (strcmp(type, "UPWALL_T") == 0) filter_type = 3;
  752. +    if (strcmp(type, "CEIL_T") == 0) filter_type = 4;
  753. +    if (strcmp(type, "FLOOR_H") == 0) filter_type = 5;
  754. +    if (strcmp(type, "CEIL_H") == 0) filter_type = 6;
  755. +    if (strcmp(type, "DISSOLVE") == 0) filter_type = 7;
  756. +    if (strcmp(type, "SOLID") == 0) filter_type = 8;
  757. +    if (strcmp(type, "HEIGHTFIELD") == 0) filter_type = 9;
  758. +    if (strcmp(type, "CORNER") == 0) filter_type = 10;
  759. +    if (strcmp(type, "SPACE") == 0) filter_type = 11;
  760. +    if (strcmp(type, "SUBTRACT") == 0) filter_type = 12;
  761. +    if (strcmp(type, "MERGE") == 0) filter_type = 13;
  762. +
  763. +    if (filter_type == 0)
  764. +    {
  765. +        conoutf("\f9ERROR: \f5invalid filter type");
  766. +        return;
  767. +    }
  768. +
  769. +    /** Count value arguments **/
  770. +
  771. +    int num_v = 0;
  772. +
  773. +    if (strcmp(v1, "") != 0) num_v++;
  774. +
  775. +    if (strcmp(v2, "") != 0) num_v++;
  776. +
  777. +    if (strcmp(v3, "") != 0) num_v++;
  778. +
  779. +    if (strcmp(v4, "") != 0) num_v++;
  780. +
  781. +    if (strcmp(v5, "") != 0) num_v++;
  782. +
  783. +    if (strcmp(v6, "") != 0) num_v++;
  784. +
  785. +    if (strcmp(v7, "") != 0) num_v++;
  786. +
  787. +    if (num_v < 1 && filter_type != 12 && filter_type != 13)
  788. +    {
  789. +        conoutf("\f9ERROR: \f5this filter requires at least one key value");
  790. +        return;
  791. +    }
  792. +
  793. +    int v [num_v];
  794. +
  795. +    if (num_v > 0) v[0] = atoi(v1);
  796. +    if (num_v > 1) v[1] = atoi(v2);
  797. +    if (num_v > 2) v[2] = atoi(v3);
  798. +    if (num_v > 3) v[3] = atoi(v4);
  799. +    if (num_v > 4) v[4] = atoi(v5);
  800. +    if (num_v > 5) v[5] = atoi(v6);
  801. +    if (num_v > 6) v[6] = atoi(v7);
  802. +
  803. +    int count = 0;
  804. +
  805. +    if (strcmp(v1, "") != 0)
  806. +    count = expandsel(v[0]); //expand selections to 1 x 1 selections
  807. +    else
  808. +    count = expandsel(1);
  809. +
  810. +    /** filter selection(s) */
  811. +
  812. +    bool match; //match found
  813. +
  814. +    loopv(sels)
  815. +    {
  816. +        sqr *s = S((sels[i]).x, (sels[i]).y);
  817. +        match = false;
  818. +
  819. +        switch(filter_type)
  820. +        {
  821. +            case 1: //floor texture
  822. +            loopj (num_v)
  823. +            {
  824. +                if (s->ftex == v[j])
  825. +                {
  826. +                    match = true;
  827. +                    break;
  828. +                }
  829. +            }
  830. +
  831. +            //no match by end of iteration
  832. +
  833. +            if (!match)
  834. +            {
  835. +                sels.remove(i);
  836. +                i--;
  837. +            }
  838. +
  839. +            break;
  840. +
  841. +            case 2: //wall texture
  842. +            loopj (num_v)
  843. +            {
  844. +                if (s->wtex == v[j])
  845. +                {
  846. +                    match = true;
  847. +                    break;
  848. +                }
  849. +            }
  850. +
  851. +            //no match by end of iteration
  852. +
  853. +            if (!match)
  854. +            {
  855. +                sels.remove(i);
  856. +                i--;
  857. +            }
  858. +
  859. +            break;
  860. +
  861. +            case 3: // upper wall texture
  862. +            loopj (num_v)
  863. +            {
  864. +                if (s->utex == v[j])
  865. +                {
  866. +                    match = true;
  867. +                    break;
  868. +                }
  869. +            }
  870. +
  871. +            //no match by end of iteration
  872. +
  873. +            if (!match)
  874. +            {
  875. +                sels.remove(i);
  876. +                i--;
  877. +            }
  878. +
  879. +            break;
  880. +
  881. +            case 4: //ceiling texture
  882. +            loopj (num_v)
  883. +            {
  884. +                if (s->ctex == v[j])
  885. +                {
  886. +                    match = true;
  887. +                    break;
  888. +                }
  889. +            }
  890. +
  891. +            //no match by end of iteration
  892. +
  893. +            if (!match)
  894. +            {
  895. +                sels.remove(i);
  896. +                i--;
  897. +            }
  898. +
  899. +            break;
  900. +
  901. +            case 5: //floor height
  902. +            loopj (num_v)
  903. +            {
  904. +                if (s->floor == v[j])
  905. +                {
  906. +                    match = true;
  907. +                    break;
  908. +                }
  909. +            }
  910. +
  911. +            //no match by end of iteration
  912. +
  913. +            if (!match)
  914. +            {
  915. +                sels.remove(i);
  916. +                i--;
  917. +            }
  918. +
  919. +            break;
  920. +
  921. +            case 6: //ceiling height
  922. +            loopj (num_v)
  923. +            {
  924. +                if (s->ceil == v[j])
  925. +                {
  926. +                    match = true;
  927. +                    break;
  928. +                }
  929. +            }
  930. +
  931. +            //no match by end of iteration
  932. +
  933. +            if (!match)
  934. +            {
  935. +                sels.remove(i);
  936. +                i--;
  937. +            }
  938. +
  939. +            break;
  940. +
  941. +            case 7: //dissolve
  942. +            if (1 + rand()%99 < v[0]) //frequency
  943. +            {
  944. +                sels.remove(i);
  945. +                i--;
  946. +            }
  947. +            break;
  948. +
  949. +            case 8: //solid
  950. +            if (v[0] < 1) //if / if not
  951. +            {
  952. +                if (s->type == SOLID)
  953. +                {
  954. +                    sels.remove(i);
  955. +                    i--;
  956. +                }
  957. +            }
  958. +            else if (s->type != SOLID)
  959. +            {
  960. +                sels.remove(i);
  961. +                i--;
  962. +            }
  963. +            break;
  964. +
  965. +            case 9: //heightfield
  966. +            if (v[0] < 1) //if / if not
  967. +            {
  968. +                if (s->type == FHF || s->type == CHF)
  969. +                {
  970. +                    sels.remove(i);
  971. +                    i--;
  972. +                }
  973. +            }
  974. +            else if (s->type != FHF && s->type != CHF)
  975. +            {
  976. +                sels.remove(i);
  977. +                i--;
  978. +            }
  979. +            break;
  980. +
  981. +            case 10: //corner
  982. +            if (v[0] < 1) //if / if not
  983. +            {
  984. +                if (s->type == CORNER)
  985. +                {
  986. +                    sels.remove(i);
  987. +                    i--;
  988. +                }
  989. +            }
  990. +            else if (s->type != CORNER)
  991. +            {
  992. +                sels.remove(i);
  993. +                i--;
  994. +            }
  995. +            break;
  996. +
  997. +            case 11: //space
  998. +            if (v[0] < 1) //if / if not
  999. +            {
  1000. +                if (s->type == SPACE)
  1001. +                {
  1002. +                    sels.remove(i);
  1003. +                    i--;
  1004. +                }
  1005. +            }
  1006. +            else if (s->type != SPACE)
  1007. +            {
  1008. +                sels.remove(i);
  1009. +                i--;
  1010. +            }
  1011. +            break;
  1012. +
  1013. +            default:
  1014. +            break;
  1015. +        }
  1016. +    }
  1017. +
  1018. +    if (!sels.empty()) //if there is a selection to simplify
  1019. +    {
  1020. +        if (filter_type == 12 && count > 0) //remove
  1021. +        compress_sel(count);
  1022. +        else
  1023. +        compress_sel(0);
  1024. +    }
  1025. +
  1026. +    fixselh();
  1027. +}
  1028. +
  1029. +COMMAND (filter_sel, "ssssssss");
  1030. +
  1031. +extern float Mh;
  1032. +
  1033. +void select_all()
  1034. +{
  1035. +    resetselections();
  1036. +    addselection(mapdims[0] - 1, mapdims[1] - 1, mapdims[2] - mapdims[0] + 3, mapdims[3] - mapdims[1] + 3, Mh);
  1037. +}
  1038. +
  1039. +COMMAND (select_all, "");
  1040. +
  1041. +struct Slot
  1042. +{
  1043. +    string name;
  1044. +    float scale;
  1045. +    Texture *tex;
  1046. +    bool loaded;
  1047. +};
  1048. +
  1049. +extern vector<Slot> slots;
  1050. +
  1051. +void texname(const char* pos)
  1052. +{
  1053. +    if (noselection())
  1054. +    {
  1055. +        result("first make a selection");
  1056. +        return;
  1057. +    }
  1058. +
  1059. +    sqr *s = 0; //cube
  1060. +    int t = -1; //type
  1061. +
  1062. +    /** get type to check **/
  1063. +
  1064. +    if (strcmp(pos, "FLOOR") == 0) t = 0;
  1065. +    else if (strcmp(pos, "WALL") == 0) t = 1;
  1066. +    else if (strcmp(pos, "UPWALL") == 0) t = 2;
  1067. +    else if (strcmp(pos, "CEIL") == 0) t = 3;
  1068. +    else
  1069. +    {
  1070. +        conoutf("\f9ERROR: \f5invalid position argument");
  1071. +        result("-1");
  1072. +        return;
  1073. +    }
  1074. +
  1075. +    s = S((sels[sels.length() - 1]).x, (sels[sels.length() - 1]).y);
  1076. +
  1077. +    if (!s)
  1078. +    {
  1079. +        result("error");
  1080. +        return;
  1081. +    }
  1082. +
  1083. +    switch (t)
  1084. +    {
  1085. +        case 0:
  1086. +        result(slots[s->ftex].tex->name);
  1087. +        break;
  1088. +
  1089. +        case 1:
  1090. +        result(slots[s->wtex].tex->name);
  1091. +        break;
  1092. +
  1093. +        case 2:
  1094. +        result(slots[s->utex].tex->name);
  1095. +        break;
  1096. +
  1097. +        case 3:
  1098. +        result(slots[s->ctex].tex->name);
  1099. +        break;
  1100. +
  1101. +        default:
  1102. +        result("error");
  1103. +    }
  1104. +}
  1105. +
  1106. +COMMAND(texname, "s");
  1107. +
  1108. +int getcurtex(const char* pos, const char* x, const char* y) //returns index of texture slot
  1109. +{
  1110. +    /** Count arguments **/
  1111. +    int num_args = 0;
  1112. +
  1113. +    if (strcmp(pos, "") != 0)
  1114. +    num_args++;
  1115. +
  1116. +    if (strcmp(x, "") != 0)
  1117. +    num_args++;
  1118. +
  1119. +    if (strcmp(y, "") != 0)
  1120. +    num_args++;
  1121. +
  1122. +    if (num_args == 1) //working from selection
  1123. +    {
  1124. +        if (noselection())
  1125. +        {
  1126. +            result("-1");
  1127. +            return -1;
  1128. +        }
  1129. +    }
  1130. +
  1131. +    if (num_args == 2)
  1132. +    {
  1133. +        conoutf("\f9ERROR: \f5missing Y argument");
  1134. +        result("-1");
  1135. +        return -1;
  1136. +    }
  1137. +
  1138. +    /**/
  1139. +
  1140. +    sqr *s = 0; //cube
  1141. +    int t = -1; //type
  1142. +
  1143. +    /** get type to check **/
  1144. +
  1145. +    if (strcmp(pos, "FLOOR") == 0) t = 0;
  1146. +    else if (strcmp(pos, "WALL") == 0) t = 1;
  1147. +    else if (strcmp(pos, "UPWALL") == 0) t = 2;
  1148. +    else if (strcmp(pos, "CEIL") == 0) t = 3;
  1149. +    else
  1150. +    {
  1151. +        conoutf("\f9ERROR: \f5invalid position argument");
  1152. +        result("-1");
  1153. +        return -1;
  1154. +    }
  1155. +
  1156. +    /**/
  1157. +
  1158. +    int X = atoi(x);
  1159. +    int Y = atoi(y);
  1160. +
  1161. +    switch (num_args)
  1162. +    {
  1163. +        case 1:
  1164. +        s = S((sels[sels.length() - 1]).x, (sels[sels.length() - 1]).y);
  1165. +        break;
  1166. +
  1167. +        case 3:
  1168. +        if (OUTBORD(X, Y))
  1169. +        {
  1170. +            conoutf("\f9ERROR: \f5coordinates out of bounds");
  1171. +            result("-1");
  1172. +            return -1;
  1173. +        }
  1174. +        s = S(X, Y);
  1175. +        break;
  1176. +
  1177. +        default:
  1178. +        result("-1");
  1179. +        return -1;
  1180. +    }
  1181. +
  1182. +    string buf = "";
  1183. +
  1184. +    switch (t)
  1185. +    {
  1186. +        case 0:
  1187. +        concatformatstring(buf, "%d ", s->ftex);
  1188. +        result(buf);
  1189. +        return s->ftex;
  1190. +
  1191. +        case 1:
  1192. +        concatformatstring(buf, "%d ", s->wtex);
  1193. +        result(buf);
  1194. +        return s->wtex;
  1195. +
  1196. +        case 2:
  1197. +        concatformatstring(buf, "%d ", s->utex);
  1198. +        result(buf);
  1199. +        return s->utex;
  1200. +
  1201. +        case 3:
  1202. +        concatformatstring(buf, "%d ", s->ctex);
  1203. +        result(buf);
  1204. +        return s->ctex;
  1205. +
  1206. +        default:
  1207. +        result("-1");
  1208. +        return -1;
  1209. +    }
  1210. +
  1211. +    result("-1");
  1212. +    return -1;
  1213. +}
  1214. +
  1215. +void curtex(const char* pos, const char* x, const char* y) //prints texture slot info
  1216. +{
  1217. +    /** Count arguments **/
  1218. +
  1219. +    int num_args = 0;
  1220. +
  1221. +    if (strcmp(pos, "") != 0)
  1222. +    num_args++;
  1223. +
  1224. +    if (strcmp(x, "") != 0)
  1225. +    num_args++;
  1226. +
  1227. +    if (strcmp(y, "") != 0)
  1228. +    num_args++;
  1229. +
  1230. +    if (num_args < 2) //working from selection
  1231. +    {
  1232. +        if (noselection())
  1233. +        return;
  1234. +    }
  1235. +
  1236. +    if (num_args == 2)
  1237. +    {
  1238. +        conoutf("\f9ERROR: \f5missing Y argument");
  1239. +        return;
  1240. +    }
  1241. +
  1242. +    /**/
  1243. +
  1244. +    sqr *s = 0; //cube
  1245. +    int t = -1; //type
  1246. +
  1247. +    /** get type to check **/
  1248. +
  1249. +    if (strcmp(pos, "FLOOR") == 0) t = 0;
  1250. +    else if (strcmp(pos, "WALL") == 0) t = 1;
  1251. +    else if (strcmp(pos, "UPWALL") == 0) t = 2;
  1252. +    else if (strcmp(pos, "CEIL") == 0) t = 3;
  1253. +    else if (strcmp(pos, "ALL") == 0 || num_args == 0) t = 4;
  1254. +    else
  1255. +    {
  1256. +        conoutf("\f9ERROR: \f5invalid position argument");
  1257. +        return;
  1258. +    }
  1259. +
  1260. +    /**/
  1261. +
  1262. +    int X = atoi(x);
  1263. +    int Y = atoi(y);
  1264. +
  1265. +    switch (num_args)
  1266. +    {
  1267. +        case 0:
  1268. +        case 1:
  1269. +        s = S((sels[sels.length() - 1]).x, (sels[sels.length() - 1]).y);
  1270. +        break;
  1271. +
  1272. +        case 3:
  1273. +
  1274. +        if (OUTBORD(X, Y))
  1275. +        {
  1276. +            conoutf("\f9ERROR: \f5coordinates out of bounds");
  1277. +            return;
  1278. +        }
  1279. +        s = S(X, Y);
  1280. +        break;
  1281. +
  1282. +        default:
  1283. +        return;
  1284. +    }
  1285. +
  1286. +    switch (t)
  1287. +    {
  1288. +        case 0:
  1289. +        conoutf("The \fPfloor \f5texture of this cube is slot number \fN%i", s->ftex);
  1290. +        conoutf("\fM--------------------------------------------------------------");
  1291. +        break;
  1292. +
  1293. +        case 1:
  1294. +        conoutf("The \fPwall \f5texture of this cube is slot number \fN%i", s->wtex);
  1295. +        conoutf("\fM--------------------------------------------------------------");
  1296. +        break;
  1297. +
  1298. +        case 2:
  1299. +        conoutf("The \fPupper wall \f5texture of this cube is slot number \fN%i", s->utex);
  1300. +        conoutf("\fM--------------------------------------------------------------");
  1301. +        break;
  1302. +
  1303. +        case 3:
  1304. +        conoutf("The \fPceiling \f5texture of this cube is slot number \fN%i", s->ctex);
  1305. +        conoutf("\fM--------------------------------------------------------------");
  1306. +        break;
  1307. +
  1308. +        case 4:
  1309. +        conoutf("The \fPfloor \f5texture of this cube is slot number \fN%i", s->ftex);
  1310. +        conoutf("The \fPwall \f5texture of this cube is slot number \fN%i", s->wtex);
  1311. +        conoutf("The \fPupper wall \f5texture of this cube is slot number \fN%i", s->utex);
  1312. +        conoutf("The \fPceiling \f5texture of this cube is slot number \fN%i", s->ctex);
  1313. +        conoutf("\fM--------------------------------------------------------------");
  1314. +
  1315. +        default:
  1316. +        return;
  1317. +    }
  1318. +}
  1319. +
  1320. +COMMAND(curtex, "sss");
  1321. +COMMAND(getcurtex, "sss");
  1322. +
  1323. +int getcurheight(const char* pos, const char* x, const char* y) //returns height of cubes
  1324. +{
  1325. +    /** Count arguments **/
  1326. +    int num_args = 0;
  1327. +
  1328. +    if (strcmp(pos, "") != 0)
  1329. +    num_args++;
  1330. +
  1331. +    if (strcmp(x, "") != 0)
  1332. +    num_args++;
  1333. +
  1334. +    if (strcmp(y, "") != 0)
  1335. +    num_args++;
  1336. +
  1337. +    if (num_args < 2) //working from selection
  1338. +    {
  1339. +        if (noselection())
  1340. +        {
  1341. +            result("-255");
  1342. +            return -255;
  1343. +        }
  1344. +
  1345. +        if (num_args == 0)
  1346. +        {
  1347. +            conoutf("\f9ERROR: \f5getcurheight cannot be called with no arguments");
  1348. +            result("-255");
  1349. +            return -255;
  1350. +        }
  1351. +    }
  1352. +
  1353. +    if (num_args == 2)
  1354. +    {
  1355. +        conoutf("\f9ERROR: \f5missing Y argument");
  1356. +        result("-255");
  1357. +        return -255;
  1358. +    }
  1359. +
  1360. +    /**/
  1361. +
  1362. +    sqr *s = 0; //cube
  1363. +    int p = -1; //position
  1364. +
  1365. +    /** get type to check **/
  1366. +
  1367. +    if (strcmp(pos, "FLOOR") == 0) p = 0;
  1368. +    else if (strcmp(pos, "CEIL") == 0) p = 1;
  1369. +    else
  1370. +    {
  1371. +        conoutf("\f9ERROR: \f5invalid position argument");
  1372. +        result("-255");
  1373. +        return -255;
  1374. +    }
  1375. +
  1376. +    /** Grab cube **/
  1377. +
  1378. +    int X = atoi(x);
  1379. +    int Y = atoi(y);
  1380. +
  1381. +    switch (num_args)
  1382. +    {
  1383. +        case 1:
  1384. +        s = S((sels[sels.length() - 1]).x, (sels[sels.length() - 1]).y);
  1385. +        break;
  1386. +
  1387. +        case 3:
  1388. +        if (OUTBORD(X, Y))
  1389. +        {
  1390. +            conoutf("\f9ERROR: \f5coordinates out of bounds");
  1391. +            result("-255");
  1392. +            return -255;
  1393. +        }
  1394. +        s = S(X, Y);
  1395. +        break;
  1396. +
  1397. +        default:
  1398. +        result("-255");
  1399. +        return -255;
  1400. +    }
  1401. +
  1402. +    /** get height **/
  1403. +
  1404. +    string buf = "";
  1405. +
  1406. +    switch (p)
  1407. +    {
  1408. +        case 0:
  1409. +        concatformatstring(buf, "%d ", s->floor);
  1410. +        result(buf);
  1411. +        return s->floor;
  1412. +
  1413. +        case 1:
  1414. +        concatformatstring(buf, "%d ", s->ceil);
  1415. +        result(buf);
  1416. +        return s->ceil;
  1417. +
  1418. +        default:
  1419. +        result("-255");
  1420. +        return -255;
  1421. +    }
  1422. +
  1423. +    result("-255");
  1424. +    return -255;
  1425. +}
  1426. +
  1427. +void curheight(const char* pos, const char* x, const char* y) //prints height of cubes
  1428. +{
  1429. +    /** Count arguments **/
  1430. +    int num_args = 0;
  1431. +
  1432. +    if (strcmp(pos, "") != 0)
  1433. +    num_args++;
  1434. +
  1435. +    if (strcmp(x, "") != 0)
  1436. +    num_args++;
  1437. +
  1438. +    if (strcmp(y, "") != 0)
  1439. +    num_args++;
  1440. +
  1441. +    if (num_args < 2) //working from selection
  1442. +    {
  1443. +        if (noselection())
  1444. +        return;
  1445. +    }
  1446. +
  1447. +    if (num_args == 2)
  1448. +    {
  1449. +        conoutf("\f9ERROR: \f5missing Y argument");
  1450. +        return;
  1451. +    }
  1452. +
  1453. +    /**/
  1454. +
  1455. +    sqr *s = 0; //cube
  1456. +    int p = -1; //position
  1457. +
  1458. +    /** get type to check **/
  1459. +
  1460. +    if (strcmp(pos, "FLOOR") == 0) p = 0;
  1461. +    else if (strcmp(pos, "CEIL") == 0) p = 1;
  1462. +    else if (num_args == 0 || strcmp(pos, "BOTH") == 0) p = 2;
  1463. +    else
  1464. +    {
  1465. +        conoutf("\f9ERROR: \f5invalid position argument");
  1466. +        return;
  1467. +    }
  1468. +
  1469. +    /** Grab cube **/
  1470. +
  1471. +    int X = atoi(x);
  1472. +    int Y = atoi(y);
  1473. +
  1474. +    switch (num_args)
  1475. +    {
  1476. +        case 0:
  1477. +        case 1:
  1478. +        s = S((sels[sels.length() - 1]).x, (sels[sels.length() - 1]).y);
  1479. +        break;
  1480. +
  1481. +        case 3:
  1482. +        if (OUTBORD(X, Y))
  1483. +        {
  1484. +            conoutf("\f9ERROR: \f5coordinates out of bounds");
  1485. +            return;
  1486. +        }
  1487. +        s = S(X, Y);
  1488. +        break;
  1489. +
  1490. +        default:
  1491. +        return;
  1492. +    }
  1493. +
  1494. +    /** get height **/
  1495. +
  1496. +    switch (p)
  1497. +    {
  1498. +        case 0:
  1499. +        conoutf("The \fPfloor \f5height of this cube is \fN%i", s->floor);
  1500. +        conoutf("\fM--------------------------------------------------------------");
  1501. +        break;
  1502. +
  1503. +        case 1:
  1504. +        conoutf("The \fPceiling \f5height of this cube is \fN%i", s->ceil);
  1505. +        conoutf("\fM--------------------------------------------------------------");
  1506. +        break;
  1507. +
  1508. +        case 2:
  1509. +        conoutf("The \fPfloor \f5height of this cube is \fN%i", s->floor);
  1510. +        conoutf("The \fPceiling \f5height of this cube is \fN%i", s->ceil);
  1511. +        conoutf("\fM--------------------------------------------------------------");
  1512. +
  1513. +        default:
  1514. +        return;
  1515. +    }
  1516. +}
  1517. +
  1518. +COMMAND(getcurheight, "sss");
  1519. +COMMAND(curheight, "sss");
  1520. +
  1521. +void undo_sel(char* n) //removes last selection
  1522. +{
  1523. +    if (sels.empty())
  1524. +    {
  1525. +        conoutf("no selections to remove");
  1526. +        return;
  1527. +    }
  1528. +
  1529. +    int num;
  1530. +
  1531. +    if (strcmp(n, "") != 0) num = atoi(n);
  1532. +    else
  1533. +    num = 1;
  1534. +
  1535. +    while (num > 0)
  1536. +    {
  1537. +        if (sels.empty())
  1538. +        {
  1539. +            conoutf("no more selections to remove");
  1540. +            return;
  1541. +        }
  1542. +
  1543. +        sels.pop();
  1544. +        num--;
  1545. +    }
  1546. +}
  1547. +
  1548. +COMMAND (undo_sel, "s");
  1549.  
  1550. void replace()
  1551. {
  1552. @@ -528,6 +1790,42 @@
  1553. }
  1554.  
  1555. COMMAND(equalize, "i");
  1556. +
  1557. +void equalize_sels(int *flr) //equalizes *all* sels instead of *each* sel
  1558. +{
  1559. +    bool isfloor = *flr==0;
  1560. +    EDITSEL;
  1561. +
  1562. +    int hi = 0;
  1563. +    int low = 0;
  1564. +
  1565. +    loopv(sels) //collect min/max info
  1566. +    {
  1567. +        block &sel = sels[i];
  1568. +
  1569. +        loopselxy(sel,
  1570. +        {
  1571. +            if(s->floor<low) low = s->floor;
  1572. +            if(s->ceil>hi) hi = s->ceil;
  1573. +        });
  1574. +    }
  1575. +
  1576. +    loopv(sels) //height asignments
  1577. +    {
  1578. +        block &sel = sels[i];
  1579. +
  1580. +        loopselxy(sel,
  1581. +        {
  1582. +            if(isfloor) s->floor = low; else s->ceil = hi;
  1583. +            if(s->floor>=s->ceil) s->floor = s->ceil-1;
  1584. +        });
  1585. +
  1586. +        addmsg(SV_EDITE, "ri5", sel.x, sel.y, sel.xs, sel.ys, isfloor);
  1587. +    }
  1588. +
  1589. +}
  1590. +
  1591. +COMMAND(equalize_sels, "i");
  1592.  
  1593. void setvdeltaxy(int delta, block &sel)
  1594. {
  1595. --- entities.cpp    Tue Oct 22 13:57:16 2013
  1596. +++ entities.cpp    Fri May 23 02:52:06 2014
  1597. @@ -3,7 +3,9 @@
  1598. #include "cube.h"
  1599.  
  1600. VAR(showclips, 0, 1, 1);
  1601. -VAR(showmodelclipping, 0, 0, 1);
  1602. +VAR(showmodelclipping, 0, 0, 1);
  1603. +
  1604. +extern bool cleanedit;
  1605.  
  1606. vector<entity> ents;
  1607. vector<int> eh_ents; // edithide entities
  1608. @@ -26,7 +28,10 @@
  1609.   }
  1610.  
  1611. void renderclip(entity &e)
  1612. -{
  1613. +{
  1614. +    if (cleanedit)
  1615. +    return;
  1616. +
  1617.      float xradius = max(float(e.attr2), 0.1f), yradius = max(float(e.attr3), 0.1f);
  1618.      vec bbmin(e.x - xradius, e.y - yradius, float(S(e.x, e.y)->floor+e.attr1)),
  1619.          bbmax(e.x + xradius, e.y + yradius, bbmin.z + max(float(e.attr4), 0.1f));
  1620. @@ -124,7 +129,10 @@
  1621. COMMAND(seteditshow, "s");
  1622.  
  1623. void renderentarrow(const entity &e, const vec &dir, float radius)
  1624. -{
  1625. +{
  1626. +    if (cleanedit)
  1627. +    return;
  1628. +
  1629.      if(radius <= 0) return;
  1630.      float arrowsize = min(radius/8, 0.5f);
  1631.      vec epos(e.x, e.y, e.z);
  1632. @@ -153,11 +161,13 @@
  1633.      glEnable(GL_CULL_FACE);
  1634.      glEnable(GL_TEXTURE_2D);
  1635. }
  1636. +
  1637. +extern int globalfps;
  1638.  
  1639. void renderentities()
  1640. {
  1641.      int closest = editmode ? closestent() : -1;
  1642. -    if(editmode && !reflecting && !refracting && !stenciling)
  1643. +    if(editmode && !reflecting && !refracting && !stenciling && !cleanedit)
  1644.      {
  1645.          static int lastsparkle = 0;
  1646.          if(lastmillis - lastsparkle >= 20)
  1647. @@ -174,29 +184,49 @@
  1648.                  vec v(e.x, e.y, e.z);
  1649.                  if(vec(v).sub(camera1->o).dot(camdir) < 0) continue;
  1650.                  //particle_splash(i == closest ? PART_ELIGHT : PART_ECLOSEST, 2, 40, v);
  1651. -                int sc = PART_ECARROT; // "carrot" (orange) - entity slot currently unused, possibly "reserved"
  1652. +                int sc = PART_ELIGHT;
  1653.                  if(i==closest)
  1654.                  {
  1655. -                    sc = PART_ECLOSEST; // blue
  1656. -                }
  1657. -                else switch(e.type)
  1658. +                    sc = PART_ECLOSEST; // smoke
  1659. +                    particle_splash(PART_ECLOSEST, 1, 80, v);
  1660. +                }
  1661. +
  1662. +                switch(e.type)
  1663.                  {
  1664. -                    case LIGHT : sc = PART_ELIGHT; break; // white
  1665. -                    case PLAYERSTART: sc = PART_ESPAWN; break; // green
  1666. +                    case LIGHT : sc = PART_ELIGHT; break; // white
  1667. +
  1668. +                    case PLAYERSTART:
  1669. +                    if (e.attr2 == 0)
  1670. +                    {sc = PART_RED; break;} // CLA
  1671. +                    else if (e.attr2 == 1)
  1672. +                    {sc = PART_BLUE; break;} // RVSF
  1673. +                    else
  1674. +                    sc = PART_GREEN; break; // FFA
  1675. +
  1676.                      case I_CLIPS:
  1677. -                    case I_AMMO:
  1678. -                    case I_GRENADE: sc = PART_EAMMO; break; // red
  1679. +                    case I_AMMO:
  1680. +                    case I_AKIMBO:
  1681. +                    case I_GRENADE: sc = PART_EAMMO; break; // orange
  1682.                      case I_HEALTH:
  1683.                      case I_HELMET:
  1684. -                    case I_ARMOUR:
  1685. -                    case I_AKIMBO: sc = PART_EPICKUP; break; // yellow
  1686. -                    case MAPMODEL:
  1687. -                    case SOUND: sc = PART_EMODEL; break; // magenta
  1688. -                    case LADDER:
  1689. -                    case CLIP:
  1690. -                    case PLCLIP: sc = PART_ELADDER; break; // grey
  1691. -                    case CTF_FLAG: sc = PART_EFLAG; break; // turquoise
  1692. -                    default: break;
  1693. +                    case I_ARMOUR: sc = PART_EPICKUP; break; // yellow
  1694. +                    case MAPMODEL: sc = PART_EMODEL; break; // magenta
  1695. +                    case LADDER: sc = PART_ELADDER; break; // grey
  1696. +
  1697. +                    case CLIP: sc = PART_CLIP; break; // yellow (color of the clip)
  1698. +                    case PLCLIP: sc = PART_PLCLIP; break; // magenta (color of the clip)
  1699. +
  1700. +                    case CTF_FLAG:
  1701. +                    if (e.attr2 == 0) // CLA
  1702. +                    {sc = PART_RED; break;}
  1703. +                    else if (e.attr2 == 1) // RVSF
  1704. +                    {sc = PART_BLUE; break;}
  1705. +                    else
  1706. +                    {sc = PART_ELIGHT; break;}
  1707. +
  1708. +                    default: break;
  1709. +
  1710. +                    case SOUND: sc = 22; break; // cyan
  1711.                  }
  1712.                  //particle_splash(sc, i==closest?6:2, i==closest?120:40, v);
  1713.                  particle_splash(sc, 2, 40, v);
  1714. @@ -240,8 +270,14 @@
  1715.              switch(e.type)
  1716.              {
  1717.                  case PLAYERSTART:
  1718. -                {
  1719. -                    glColor3f(0, 1, 1);
  1720. +                {
  1721. +                    if (e.attr2 == 0)
  1722. +                    glColor3f(1, 0, 0); // CLA
  1723. +                    else if (e.attr2 == 1)
  1724. +                    glColor3f(0, 0, 1); // RVSF
  1725. +                    else
  1726. +                    glColor3f(0, 1, 0); // FFA
  1727. +
  1728.                      vec dir;
  1729.                      vecfromyawpitch(e.attr1, 0, -1, 0, dir);
  1730.                      renderentarrow(e, dir, 4);
  1731. --- main.cpp    Tue Oct 29 04:33:15 2013
  1732. +++ main.cpp    Mon May 19 23:38:43 2014
  1733. @@ -1280,7 +1280,9 @@
  1734.          serverslice(0);
  1735.  
  1736.          if(elapsed) fps = (1000.0f/elapsed+fps*10)/11; // avoid DIV-by-0
  1737. -        frames++;
  1738. +        frames++;
  1739. +
  1740. +        globalfps = fps;
  1741.  
  1742.          audiomgr.updateaudio();
  1743.  
  1744. @@ -1322,4 +1324,4 @@
  1745. }
  1746.  
  1747. VAR(version, 1, AC_VERSION, 0);
  1748. -VAR(protocol, 1, PROTOCOL_VERSION, 0);
  1749. \ No newline at end of file
  1750. +VAR(protocol, 1, PROTOCOL_VERSION, 0);
  1751. --- Makefile    Sat Nov 09 18:12:11 2013
  1752. +++ Makefile    Wed Apr 16 20:37:19 2014
  1753. @@ -1,6 +1,12 @@
  1754. -CXXFLAGS= -O3 -fomit-frame-pointer
  1755. -CXX=clang++    # Use clang++, as g++ optimizations cause crashes...
  1756. -override CXXFLAGS+= -Wall -fsigned-char
  1757. +
  1758. +
  1759. +CXXFLAGS= -O3 -fomit-frame-pointer -Wno-unused-variable
  1760. +ifneq (,$(findstring MINGW,$(PLATFORM)))
  1761. +  CXXFLAGS+= -Wall -fsigned-char
  1762. +else
  1763. +  CXX=clang++   # Use clang++, as g++ optimizations cause crashes...
  1764. +  override CXXFLAGS+= -Wall -fsigned-char
  1765. +endif
  1766.  
  1767. PLATFORM= $(shell uname -s)
  1768. PLATFORM_PREFIX=native
  1769. @@ -392,3 +398,4 @@
  1770. master-standalone.o: cube.h platform.h tools.h geom.h model.h protocol.h
  1771. master-standalone.o: sound.h weapon.h entity.h world.h i18n.h command.h
  1772. master-standalone.o: varray.h vote.h console.h protos.h
  1773. +
  1774. --- physics.cpp    Tue Oct 22 13:57:19 2013
  1775. +++ physics.cpp    Thu May 22 20:37:00 2014
  1776. @@ -474,7 +474,7 @@
  1777.                      }
  1778.                  }
  1779.  
  1780. -                if(timeinair > 200 && !pl->timeinair)
  1781. +                if(timeinair > 200 && !pl->timeinair && !water)
  1782.                  {
  1783.                      int sound = timeinair > 800 ? S_HARDLAND : S_SOFTLAND;
  1784.                      if(pl->state!=CS_DEAD)
  1785. --- protos.h    Sat Nov 09 13:48:58 2013
  1786. +++ protos.h    Fri May 23 02:52:10 2014
  1787. @@ -496,7 +496,8 @@
  1788. extern void removedynlights(physent *owner);
  1789. extern block *blockcopy(const block &b);
  1790. extern void blockpaste(const block &b, int bx, int by, bool light);
  1791. -extern void blockpaste(const block &b);
  1792. +extern void blockpaste(const block &b);
  1793. +extern void halfblockpaste(const block &b, int bx, int by, bool floor);
  1794. extern void freeblock(block *&b);
  1795.  
  1796. // worldrender
  1797. @@ -626,7 +627,7 @@
  1798. {
  1799.      PART_SPARK = 0,
  1800.      PART_SMOKE,
  1801. -    PART_ECLOSEST,
  1802. +    PART_BLUE,
  1803.      PART_BLOOD,
  1804.      PART_DEMOTRACK,
  1805.      PART_FIREBALL,
  1806. @@ -637,13 +638,16 @@
  1807.      PART_HUDMUZZLEFLASH,
  1808.      PART_MUZZLEFLASH,
  1809.      PART_ELIGHT,
  1810. -    PART_ESPAWN,
  1811. -    PART_EAMMO,
  1812. +    PART_GREEN,
  1813. +    PART_RED,
  1814.      PART_EPICKUP,
  1815.      PART_EMODEL,
  1816. -    PART_ECARROT,
  1817. +    PART_EAMMO,
  1818.      PART_ELADDER,
  1819. -    PART_EFLAG
  1820. +    PART_ECLOSEST,
  1821. +    PART_SOUND = 22,
  1822. +    PART_CLIP,
  1823. +    PART_PLCLIP
  1824. };
  1825.  
  1826. extern void particleinit();
  1827. --- renderhud.cpp    Tue Oct 22 13:57:19 2013
  1828. +++ renderhud.cpp    Sat Jun 07 00:20:51 2014
  1829. @@ -1,6 +1,8 @@
  1830. // renderhud.cpp: HUD rendering
  1831.  
  1832. #include "cube.h"
  1833. +
  1834. +extern bool cleanedit;
  1835.  
  1836. void drawicon(Texture *tex, float x, float y, float s, int col, int row, float ts)
  1837. {
  1838. @@ -278,7 +280,10 @@
  1839. COMMAND(loadcrosshair, "ss");
  1840.  
  1841. void drawcrosshair(playerent *p, int n, color *c, float size)
  1842. -{
  1843. +{
  1844. +    if (cleanedit && editmode)
  1845. +    return;
  1846. +
  1847.      Texture *crosshair = crosshairs[n];
  1848.      if(!crosshair)
  1849.      {
  1850. @@ -890,7 +895,22 @@
  1851.      char *infostr = editinfo();
  1852.      int commandh = 1570 + FONTH;
  1853.      if(command) commandh -= rendercommand(20, 1570, VIRTW);
  1854. -    else if(infostr) draw_text(infostr, 20, 1570);
  1855. +
  1856. +    else if(infostr)
  1857. +    {
  1858. +        if (cleanedit)
  1859. +        {
  1860. +            glPushMatrix();
  1861. +            glLoadIdentity();
  1862. +            glOrtho(0, VIRTW*2, VIRTH*2, 0, -1, 1);
  1863. +            glScalef(1.0, 1.0, 1.0); //set scale
  1864. +            draw_text(infostr, 48, VIRTH*2 -4*FONTH);
  1865. +            glPopMatrix();
  1866. +        }
  1867. +        else
  1868. +        draw_text(infostr, 20, 1570);
  1869. +    }
  1870. +
  1871.      else if(targetplayer && showtargetname) draw_text(colorname(targetplayer), 20, 1570);
  1872.      glLoadIdentity();
  1873.      glOrtho(0, VIRTW*2, VIRTH*2, 0, -1, 1);
  1874. --- renderparticles.cpp    Tue Oct 22 13:57:19 2013
  1875. +++ renderparticles.cpp    Fri May 23 02:58:31 2014
  1876. @@ -184,7 +184,7 @@
  1877.      }
  1878. }
  1879.  
  1880. -#define MAXPARTYPES 22
  1881. +#define MAXPARTYPES 25
  1882.  
  1883. struct particle { vec o, d; int fade, type; int millis; particle *next; };
  1884. particle *parlist[MAXPARTYPES], *parempty = NULL;
  1885. @@ -252,7 +252,7 @@
  1886. {
  1887.      { PT_PART,       0.4f, 0.4f, 0.4f, 2,  0, 0.06f }, // yellow: sparks
  1888.      { PT_PART,       1.0f, 1.0f, 1.0f, 20, 1, 0.15f }, // grey:   small smoke
  1889. -    { PT_PART,       0.0f, 0.0f, 1.0f, 20, 0, 0.08f }, // blue:   edit mode closest ent
  1890. +    { PT_PART,       0.0f, 0.0f, 1.0f, 20, 0, 0.08f }, // blue:   used for RVSF related entities
  1891.      { PT_BLOOD,      0.5f, 0.0f, 0.0f, 1,  4, 0.3f  }, // red:    blood spats
  1892.      { PT_PART,       1.0f, 0.1f, 0.1f, 0,  1, 0.2f  }, // red:    demotrack
  1893.      { PT_FIREBALL,   1.0f, 0.5f, 0.5f, 0,  2, 7.0f  }, // explosion fireball
  1894. @@ -264,16 +264,19 @@
  1895.      { PT_HUDFLASH,   1.0f, 1.0f, 1.0f, 0,  6, 0.7f  }, // hudgun muzzle flash
  1896.      { PT_FLASH,      1.0f, 1.0f, 1.0f, 0,  6, 0.7f  }, // muzzle flash
  1897.      { PT_PART,       1.0f, 1.0f, 1.0f, 20, 0, 0.08f }, // white: edit mode ent type : light
  1898. -    { PT_PART,       0.0f, 1.0f, 0.0f, 20, 0, 0.08f }, // green: edit mode ent type : spawn
  1899. -    { PT_PART,       1.0f, 0.0f, 0.0f, 20, 0, 0.08f }, // red: edit mode ent type : ammo
  1900. -    { PT_PART,       1.0f, 1.0f, 0.0f, 20, 0, 0.08f }, // yellow: edit mode ent type : pickup
  1901. -    { PT_PART,       1.0f, 0.0f, 1.0f, 20, 0, 0.08f }, // magenta: edit mode ent type : model, sound
  1902. -    { PT_PART,       1.0f, 0.5f, 0.2f, 20, 0, 0.08f }, // orange: edit mode ent type : "carrot"
  1903. -    { PT_PART,       0.5f, 0.5f, 0.5f, 20, 0, 0.08f }, // grey: edit mode ent type : ladder, (pl)clip
  1904. -    { PT_PART,       0.0f, 1.0f, 1.0f, 20, 0, 0.08f }, // turquoise: edit mode ent type : CTF-flag
  1905. +    { PT_PART,       0.0f, 1.0f, 0.0f, 20, 0, 0.08f }, // green: edit mode ent type : FFA spawn
  1906. +    { PT_PART,       1.0f, 0.0f, 0.0f, 20, 0, 0.08f }, // red: used for CLA related entities
  1907. +    { PT_PART,       0.78f, 1.0f, 0.33f, 20, 0, 0.08f }, // yellow-green: edit mode ent type : pickup
  1908. +    { PT_PART,       0.6f, 0.3f, 0.9f, 20, 0, 0.08f }, // purple: edit mode ent type : mapmodel
  1909. +    { PT_PART,       1.0f, 0.5f, 0.2f, 20, 0, 0.08f }, // orange: edit mode ent type : ammo
  1910. +    { PT_PART,       0.7f, 1.0f, 1.0f, 20, 0, 0.08f }, // bright cyan: edit mode ent type : ladder,
  1911. +    { PT_PART,       0.45f, 0.45f, 0.45f, 20, 1, 0.2f }, // smoke effect: closest/selected entity
  1912.      // 2011jun18 : shotty decals
  1913.      { PT_BULLETHOLE, 0.2f, 0.2f, 1.0f, 0,  3, 0.1f  }, // hole decal M
  1914. -    { PT_BULLETHOLE, 0.2f, 1.0f, 0.2f, 0,  3, 0.1f  }, // hole decal C
  1915. +    { PT_BULLETHOLE, 0.2f, 1.0f, 0.2f, 0,  3, 0.1f  }, // hole decal C
  1916. +    { PT_PART,       0.0f, 1.0f, 1.0f, 20, 0, 0.08f }, // cyan: edit mode ent type: sound
  1917. +    { PT_PART,       1.0f, 1.0f, 0.0f, 20, 0, 0.08f }, // yellow: edit mode ent type: clip
  1918. +    { PT_PART,       1.0f, 0.0f, 1.0f, 20, 0, 0.08f } // magenta: edit mode ent type: plclip
  1919. };
  1920.  
  1921. VAR(particlesize, 20, 100, 500);
  1922. --- tools.h    Tue Oct 22 13:57:19 2013
  1923. +++ tools.h    Wed Apr 02 10:50:08 2014
  1924. @@ -424,7 +424,7 @@
  1925.  
  1926.      T &pop() { return buf[--ulen]; }
  1927.      T &last() { return buf[ulen-1]; }
  1928. -    void drop() { buf[--ulen].~T(); }
  1929. +    void drop() { buf[--ulen].~T();}
  1930.      bool empty() const { return ulen==0; }
  1931.  
  1932.      int capacity() const { return alen; }
  1933. --- world.cpp    Tue Oct 22 13:57:19 2013
  1934. +++ world.cpp    Tue May 20 19:12:15 2014
  1935. @@ -127,10 +127,24 @@
  1936.  
  1937. COMMAND(nextclosestent, "");
  1938. COMMAND(closestenttype, "s");
  1939. +
  1940. +int active_ent = -1;
  1941. +bool locking_ent = false, lockselent = false;
  1942. +
  1943. +COMMANDF(togglelockselent, "", (void) { active_ent = -1; lockselent = !lockselent; if (lockselent) locking_ent = true;});
  1944.  
  1945. int closestent()        // used for delent and edit mode ent display
  1946. {
  1947. -    if(noteditmode("closestent")) return -1;
  1948. +    if(noteditmode("closestent")) return -1;
  1949. +
  1950. +    if (lockselent && !locking_ent && active_ent != -1)
  1951. +    {
  1952. +        if (ents[active_ent].type != NOTUSED)
  1953. +        return active_ent;
  1954. +        else
  1955. +        lockselent = false;
  1956. +    }
  1957. +
  1958.      int best = -1, bcnt = 0;
  1959.      float bdist = 99999;
  1960.      loopj(3)
  1961. @@ -150,7 +164,15 @@
  1962.              {
  1963.                  if(ents[best].x == e.x && ents[best].y == e.y && ents[best].z == e.z)
  1964.                  {
  1965. -                    if(j == 2 && bcnt == clentsel) return i;
  1966. +                    if(j == 2 && bcnt == clentsel)
  1967. +                    {
  1968. +                        if (locking_ent)
  1969. +                        {
  1970. +                            active_ent = i;
  1971. +                            locking_ent = false;
  1972. +                        }
  1973. +                        return i;
  1974. +                    }
  1975.                      bcnt++;
  1976.                  }
  1977.              }
  1978. @@ -162,7 +184,14 @@
  1979.          }
  1980.          if(best < 0 || bcnt == 1) break;
  1981.          if(bcnt) clentsel %= bcnt;
  1982. -    }
  1983. +    }
  1984. +
  1985. +    if (locking_ent)
  1986. +    {
  1987. +        active_ent = best;
  1988. +        locking_ent = false;
  1989. +    }
  1990. +
  1991.      return best;
  1992. }
  1993.  
  1994. @@ -173,7 +202,16 @@
  1995.      entity &e = ents[n];
  1996.      switch(prop)
  1997.      {
  1998. -        case 0: e.attr1 += amount; break;
  1999. +        case 0:
  2000. +        if (e.type == MAPMODEL)
  2001. +        {
  2002. +            e.attr1 += amount*16;
  2003. +            while (e.attr1 > 360) e.attr1 -= 360;
  2004. +            while (e.attr1 < 0) e.attr1 += 360;
  2005. +        }
  2006. +        else e.attr1 += amount;
  2007. +        break;
  2008. +
  2009.          case 1: e.attr2 += amount; break;
  2010.          case 2: e.attr3 += amount; break;
  2011.          case 3: e.attr4 += amount; break;
  2012. @@ -371,6 +409,26 @@
  2013. }
  2014.  
  2015. COMMANDF(scalelights, "ii", (int *f, int *i) { scalelights(*f, *i); });
  2016. +
  2017. +void scalelight(int f, int intens)
  2018. +{
  2019. +    entity &e = ents[closestent()];
  2020. +    if(e.type!=LIGHT) return;
  2021. +
  2022. +    e.attr1 = e.attr1*f/100;
  2023. +    if(e.attr1<2) e.attr1 = 2;
  2024. +    if(e.attr1>32) e.attr1 = 32;
  2025. +
  2026. +    if(intens)
  2027. +    {
  2028. +        scalecomp(e.attr2, intens);
  2029. +        scalecomp(e.attr3, intens);
  2030. +        scalecomp(e.attr4, intens);
  2031. +    }
  2032. +    calclight();
  2033. +}
  2034. +
  2035. +COMMANDF(scalelight, "ii", (int *f, int *i) { scalelight(*f, *i); });
  2036.  
  2037. int findentity(int type, int index)
  2038. {
  2039. --- worldlight.cpp    Tue Oct 22 13:57:19 2013
  2040. +++ worldlight.cpp    Fri Apr 11 15:30:00 2014
  2041. @@ -369,6 +369,49 @@
  2042. {
  2043.      blockpaste(b, b.x, b.y, false);
  2044. }
  2045. +
  2046. +void halfblockpaste(const block &b, int bx, int by, bool floor)
  2047. +{
  2048. +    const sqr *q = (const sqr *)((&b)+1);
  2049. +    for(int y = by; y<b.ys+by; y++)
  2050. +    for(int x = bx; x<b.xs+bx; x++)
  2051. +    {
  2052. +        if (q->type == SOLID || q->type == CORNER ||
  2053. +        //don't override heightfields with space unnessesarily
  2054. +        (q->type == SPACE && ((floor && S(x,y)->type != CHF) || (!floor && S(x,y)->type != FHF))))
  2055. +
  2056. +        S(x,y)->type = q->type;
  2057. +
  2058. +        if (floor || q->type == SOLID)
  2059. +        {
  2060. +            if (q->type == FHF ||
  2061. +            S(x-1,y)->type == FHF ||
  2062. +            S(x,y-1)->type == FHF ||
  2063. +            S(x-1,y-1)->type == FHF)
  2064. +            //
  2065. +            {S(x,y)->type = q->type; S(x,y)->vdelta = q->vdelta;}
  2066. +
  2067. +            S(x,y)->floor = q->floor;
  2068. +            S(x,y)->wtex = q->wtex;
  2069. +            S(x,y)->ftex = q->ftex;
  2070. +        }
  2071. +        else
  2072. +        {
  2073. +            if (q->type == CHF ||
  2074. +            S(x-1,y)->type == CHF ||
  2075. +            S(x,y-1)->type == CHF ||
  2076. +            S(x-1,y-1)->type == CHF)
  2077. +            //
  2078. +            {S(x,y)->type = q->type; S(x,y)->vdelta = q->vdelta;}
  2079. +
  2080. +            S(x,y)->ceil = q->ceil;
  2081. +            S(x,y)->utex = q->utex;
  2082. +            S(x,y)->ctex = q->ctex;
  2083. +        }
  2084. +
  2085. +        q++;
  2086. +    }
  2087. +}
  2088.  
  2089. void freeblock(block *&b)
  2090. {
RAW Paste Data