[Download] 1.2 Mapping Client
#13
(14 Jun 14, 02:23AM)+f0r3v3r+ Wrote:
(13 Jun 14, 03:39PM)Music Wrote: Why don't you just release the source code?
^ This

Diff - based on 1.2.0.2 source

--- audiomanager.cpp    Tue Oct 22 13:57:19 2013
+++ audiomanager.cpp    Wed Apr 02 17:25:06 2014
@@ -554,7 +554,7 @@
// main audio update routine

void audiomanager::updateaudio()
-{
+{
     if(nosound) return;

     alcSuspendContext(context); // don't process sounds while we mess around
@@ -606,7 +606,7 @@
         {
             entity &e = ents[i];
             vec o(e.x, e.y, e.z);
-            if(e.type!=SOUND) continue;
+            if(e.type!=SOUND) continue;

             int sound = e.attr1;
             int radius = e.attr2;
--- clientgame.cpp    Tue Oct 22 13:57:19 2013
+++ clientgame.cpp    Fri Apr 11 14:43:34 2014
@@ -1116,10 +1116,13 @@
COMMAND(showmapstats, "");

VARP(showmodedescriptions, 0, 1, 1);
-extern bool canceldownloads;
+extern bool canceldownloads;
+
+extern bool lockselent;

void startmap(const char *name, bool reset)   // called just after a map load
-{
+{
+    lockselent = false;
     canceldownloads = false;
     copystring(clientmap, name);
     sendmapidenttoserver = true;
--- cube.h    Sat Nov 09 17:56:31 2013
+++ cube.h    Mon May 19 23:38:03 2014
@@ -43,7 +43,8 @@
extern vector<int> eh_ents;             // edithide entities
extern vec worldpos, camup, camright, camdir; // current target of the crosshair in the world
extern int lastmillis, totalmillis, nextmillis; // last time
-extern int curtime;                     // current frame time
+extern int curtime;                     // current frame time
+extern int globalfps;
extern int interm;
extern int gamemode, nextmode;
extern int gamespeed;
--- editing.cpp    Tue Oct 22 13:57:16 2013
+++ editing.cpp    Sat Jun 07 00:41:10 2014
@@ -3,12 +3,20 @@
#include "cube.h"

bool editmode = false;
+
+int globalfps = 0;

// the current selections, used by almost all editing commands
// invariant: all code assumes that these are kept inside MINBORD distance of the edge of the map
// => selections are checked when they are made or when the world is reloaded

-vector<block> sels;
+VAR(cleanedit, 0, 0, 1);
+COMMANDF(togglecleanedit, "", () {cleanedit = !cleanedit;});
+
+COMMANDF(clearrecenttex, "", () {loopk(3) loopi(256) hdr.texlists[k][i] = i;});
+
+vector<block> sels;
+vector<block> s_sels; //saved selections

#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); }
#define loopselsxy(b) { loopv(sels) loopselxy(sels[i], b); }
@@ -70,6 +78,20 @@
     }
     return !editmode;
}
+
+void savesel()
+{
+    s_sels = sels;
+}
+
+void reselect()
+{
+    sels = s_sels;
+}
+
+COMMAND (savesel, "");
+COMMAND (reselect, "");
+

inline bool selset()
{
@@ -81,6 +103,48 @@
     if(!selset()) conoutf("no selection");
     return !selset();
}
+
+const char *entcolor(int index) // helper function for editinfo()
+{
+    entity &e = ents[index];
+
+    switch(e.type)
+    {
+        case 2: // playerstart
+        if (e.attr2 == 0) // CLA
+        return "3";
+
+        else if (e.attr2 == 1) // RVSF
+        return "1";
+
+        else return "J"; // FFA
+
+        case 3: case 4: case 5: case 9: return "9"; // pistol clip, ammobox, grenade, akimbo
+        case 6: case 7: case 8: return "H"; // health pack, helmet, armor
+        case 10: return "T"; // mapmodel
+
+        case 12: return "M"; // ladder
+
+        case 13: // ctf-flag
+        if (e.attr2 == 0) // CLA
+        return "3";
+
+        else if (e.attr2 == 1) // RVSF
+        return "1";
+        break;
+
+        case 14: return "P"; // sound
+
+        case 15: return "2"; // clip
+        case 16: return "X"; // plclip
+
+        default:
+        return "5"; // white
+    }
+    return "5"; // white
+}
+
+extern bool lockselent;

char *editinfo()
{
@@ -88,14 +152,43 @@
     if(!editmode) return NULL;
     int e = closestent();
     if(e<0) return NULL;
-    entity &c = ents[e];
+    entity &c = ents[e];
+
     string selinfo = "no selection";
-    if(selset()) formatstring(selinfo)("selection = (%d, %d)", (sels.last()).xs, (sels.last()).ys);
-    formatstring(info)("closest entity = %s (%d, %d, %d, %d), %s", entnames[c.type], c.attr1, c.attr2, c.attr3, c.attr4, selinfo);
+    if(selset()) formatstring(selinfo)("selection = (%d, %d)", (sels.last()).xs, (sels.last()).ys);
+
+    string fileinfo = "";
+    switch (c.type)
+    {
+        case SOUND:
+        if (mapsounds.inrange(c.attr1))
+        formatstring(fileinfo)("\n%s", mapsounds[c.attr1].buf->name);
+        else
+        formatstring(fileinfo)("\n\f7unregistered sound\f5");
+        break;
+
+        case MAPMODEL:
+        {
+            mapmodelinfo &mmi = getmminfo(c.attr2);
+            if (&mmi)
+            formatstring(fileinfo)("\n%s", mmi.name);
+            else
+            formatstring(fileinfo)("\n\f7unregistered mapmodel\f5");
+        }
+        break;
+
+        default:
+        break;
+    }
+
+    if (!lockselent)
+    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);
+    else
+    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);
+
     return info;
}

-
#define EDITSEL   if(noteditmode("EDITSEL") || noselection()) return
#define EDITSELMP if(noteditmode("EDITSELMP") || noselection() || multiplayer()) return
#define EDITMP    if(noteditmode("EDITMP") || multiplayer()) return
@@ -150,87 +243,182 @@

// VC8 optimizer screws up rendering somehow if this is an actual function
#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))
-
-void cursorupdate()                                     // called every frame from hud
-{
-    flrceil = ((int)(camera1->pitch>=0))*2;
-    int cyaw = ((int) camera1->yaw) % 180;
-    editaxis = editmode ? (fabs(camera1->pitch) > 65 ? 13 : (cyaw < 45 || cyaw > 135 ? 12 : 11)) : 0;
-
-    volatile float x = worldpos.x;                      // volatile needed to prevent msvc7 optimizer bug?
-    volatile float y = worldpos.y;
-    volatile float z = worldpos.z;
-
-    cx = (int)x;
-    cy = (int)y;
-
-    if(OUTBORD(cx, cy)) return;
-    sqr *s = S(cx,cy);
-
-    if(fabs(sheight(s,s,z)-z)>1)                        // selected wall
-    {
-        x += x>camera1->o.x ? 0.5f : -0.5f;             // find right wall cube
-        y += y>camera1->o.y ? 0.5f : -0.5f;
-
-        cx = (int)x;
-        cy = (int)y;
-
-        if(OUTBORD(cx, cy)) return;
-    }
-
-    if(dragging) { makesel(false); };
-
-    const int GRIDSIZE = 5;
-    const float GRIDW = 0.5f;
-    const float GRID8 = 2.0f;
-    const float GRIDS = 2.0f;
-    const int GRIDM = 0x7;
-
-    // render editing grid
-
-    if(showgrid)
-    {
-        for(int ix = cx-GRIDSIZE; ix<=cx+GRIDSIZE; ix++) for(int iy = cy-GRIDSIZE; iy<=cy+GRIDSIZE; iy++)
-        {
-
-            if(OUTBORD(ix, iy)) continue;
-            sqr *s = S(ix,iy);
-            if(SOLID(s)) continue;
-            float h1 = sheight(s, s, z);
-            float h2 = sheight(s, SWS(s,1,0,sfactor), z);
-            float h3 = sheight(s, SWS(s,1,1,sfactor), z);
-            float h4 = sheight(s, SWS(s,0,1,sfactor), z);
-            if(s->tag) linestyle(GRIDW, 0xFF, 0x40, 0x40);
-            else if(s->type==FHF || s->type==CHF) linestyle(GRIDW, 0x80, 0xFF, 0x80);
-            else linestyle(GRIDW, 0x80, 0x80, 0x80);
-            block b = { ix, iy, 1, 1 };
-            box(b, h1, h2, h3, h4);
-            linestyle(GRID8, 0x40, 0x40, 0xFF);
-            if(!(ix&GRIDM))   line(ix,   iy,   h1, ix,   iy+1, h4);
-            if(!((ix+1)&GRIDM)) line(ix+1, iy,   h2, ix+1, iy+1, h3);
-            if(!(iy&GRIDM))   line(ix,   iy,   h1, ix+1, iy,   h2);
-            if(!((iy+1)&GRIDM)) line(ix,   iy+1, h4, ix+1, iy+1, h3);
-        }
-
-        if(!SOLID(s))
-        {
-            float ih = sheight(s, s, z);
-            linestyle(GRIDS, 0xFF, 0xFF, 0xFF);
-            block b = { cx, cy, 1, 1 };
-            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));
-            linestyle(GRIDS, 0xFF, 0x00, 0x00);
-            dot(cx, cy, ih);
-            ch = (int)ih;
-        }
-    }
-
-    if(selset())
-    {
-        linestyle(GRIDS, 0xFF, 0x40, 0x40);
-        loopv(sels) box(sels[i], (float)sels[i].h, (float)sels[i].h, (float)sels[i].h, (float)sels[i].h);
-    }
-
-    glLineWidth(1);
+
+int gridalpha = 255;
+int delay = 128;
+float old_p, old_y;
+
+void cursorupdate()                                     // called every frame from hud
+{
+    if (old_p != camera1->pitch || old_y != camera1->yaw)
+    {gridalpha = 255; delay = 128;}
+    else
+    {
+        delay -= ((255 / globalfps) + 1 );
+        if (delay < 0) delay = 0;
+
+        if (!delay)
+        gridalpha -= ((gridalpha * 3 / globalfps) + 1 );
+
+        if (gridalpha < 0)
+        gridalpha = 0;
+    }
+
+    if (!gridalpha)
+    return;
+
+    old_p = camera1->pitch;
+    old_y = camera1->yaw;
+
+    flrceil = ((int)(camera1->pitch>=0))*2;
+    int cyaw = ((int) camera1->yaw) % 180;
+    editaxis = editmode ? (fabs(camera1->pitch) > 65 ? 13 : (cyaw < 45 || cyaw > 135 ? 12 : 11)) : 0;
+
+    volatile float x = worldpos.x;                      // volatile needed to prevent msvc7 optimizer bug?
+    volatile float y = worldpos.y;
+    volatile float z = worldpos.z;
+
+    cx = (int)x;
+    cy = (int)y;
+
+    if (OUTBORD(cx, cy)) return;
+    sqr *s = S(cx,cy);
+
+    if(fabs(sheight(s,s,z)-z)>1)                        // selected wall
+    {
+        x += x>camera1->o.x ? 0.5f : -0.5f;             // find right wall cube
+        y += y>camera1->o.y ? 0.5f : -0.5f;
+
+        cx = (int)x;
+        cy = (int)y;
+
+        if(OUTBORD(cx, cy)) return;
+    }
+
+    if(dragging) { makesel(false); };
+
+    const int GRIDSIZE = 5;
+    const float GRIDW = 0.5f;
+    const float GRID8 = 2.0f;
+    const float GRIDS = 2.0f;
+    const int GRIDM = 0x7;
+
+    // render editing grid
+
+    glEnable(GL_BLEND);
+    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+    for(int ix = cx-GRIDSIZE; ix<=cx+GRIDSIZE; ix++) for(int iy = cy-GRIDSIZE; iy<=cy+GRIDSIZE; iy++)
+    {
+        if(OUTBORD(ix, iy)) continue;
+        sqr *s = S(ix,iy);
+
+        //if(SOLID(s)) continue;
+
+        float h1 = sheight(s, s, z);
+        float h2 = sheight(s, SWS(s,1,0,sfactor), z);
+        float h3 = sheight(s, SWS(s,1,1,sfactor), z);
+        float h4 = sheight(s, SWS(s,0,1,sfactor), z);
+
+        /** "Tag" cube style **/
+
+        if(s->tag)
+        {
+            glLineWidth(GRIDW);
+            glColor4ub(0x40, 0x40, 0xFF, (unsigned char)gridalpha);
+        }
+
+        /** Heightfield Style **/
+
+        else if(s->type==FHF || s->type==CHF)
+        {
+            glLineWidth(GRIDW);
+            glColor4ub(0x80, 0xFF, 0x80, (unsigned char)gridalpha); //green
+        }
+
+        /** Solid cube style **/
+
+        else if(SOLID(s))
+        {
+            glLineWidth(GRID8);
+            glColor4ub(0xAB, 0x40, 0xFE, (unsigned char)gridalpha); //purple
+        }
+
+        /** Normal cube style **/
+
+        else
+        {
+            glLineWidth(GRIDW);
+            glColor4ub(0x80, 0x80, 0x80, (unsigned char)gridalpha); //grey
+        }
+
+        /** Actually drawing the grid **/
+
+        block b = { ix, iy, 1, 1 }; //set destination coordinates to draw to
+        box(b, h1, h2, h3, h4); //draw
+
+        /** The repeating 8 x 8 grid **/
+
+        /* Choosing color **/
+
+        int temp = 255 - ((255-gridalpha)*3/2); //the thicker blue appears more opaque than other lines
+        if (temp < 0) temp = 0;
+
+        glLineWidth(GRID8);
+        glColor4ub(0x40, 0x40, 0xFF, (unsigned char)temp); //blue
+
+        /* Drawing lines on this grid */
+
+        if(!(ix&GRIDM))
+        line(ix, iy, h1, ix, iy+1, h4);
+
+        if(!((ix+1)&GRIDM))
+        line(ix+1, iy, h2, ix+1, iy+1, h3);
+
+        if(!(iy&GRIDM))
+        line(ix, iy, h1, ix+1, iy, h2);
+
+        if(!((iy+1)&GRIDM))
+        line(ix, iy+1, h4, ix+1, iy+1, h3);
+    }
+
+    /** Draw white square around cube cursor is over **/
+
+
+    float ih = sheight(s, s, z);
+    {
+        glLineWidth(GRIDS);
+        glColor4ub(0xFF, 0xFF, 0xFF, (unsigned char)gridalpha); //white
+    }
+
+    block b = { cx, cy, 1, 1 };
+    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));
+
+    /** And the orienting little square in the corner **/
+
+    glLineWidth(GRIDS);
+    glColor4ub(0xFF, 0x00, 0x00, (unsigned char)gridalpha); //red
+    dot(cx, cy, ih);
+
+    ch = (int)ih; //updates height of selection box (the red boxes) to the correct height
+
+    /** Draw selection(s) **/
+
+    if(selset())
+    {
+        /* Choosing color */
+
+        glLineWidth(GRIDS);
+        glColor4ub(0xFF, 0x40, 0x40, (unsigned char)gridalpha); //red
+
+        /* Drawing */
+
+        loopv(sels) //for each selection
+        box(sels[i], (float)sels[i].h, (float)sels[i].h, (float)sels[i].h, (float)sels[i].h);
+    }
+
+    glDisable(GL_BLEND);
+    glLineWidth(1);
}

vector<block *> undos;                                  // unlimited undo
@@ -308,6 +496,44 @@
         remipmore(sel);
     }
}
+
+
+void paste_half()
+{
+    if(noteditmode("EDITSEL") || noselection()) return;
+
+    if(!copybuffers.length()) { conoutf("nothing to paste"); return; }
+
+    loopv(sels)
+    {
+        block &sel = sels[i];
+        int selx = sel.x;
+        int sely = sel.y;
+
+        loopvj(copybuffers)
+        {
+            block *copyblock = copybuffers[j];
+            int dx = copyblock->x - copybuffers[0]->x, dy = copyblock->y - copybuffers[0]->y;
+
+            sel.xs = copyblock->xs;
+            sel.ys = copyblock->ys;
+            sel.x = selx + dx;
+            sel.y = sely + dy;
+
+            if(!correctsel(sel) || sel.xs!=copyblock->xs || sel.ys!=copyblock->ys) { conoutf("incorrect selection"); return; }
+            makeundo(sel);
+
+            if (flrceil == 0)
+            halfblockpaste(*copyblock, sel.x, sel.y, true);
+            else
+            halfblockpaste(*copyblock, sel.x, sel.y, false);
+        }
+
+        remipmore(sel);
+    }
+}
+
+COMMAND(paste_half, "");

// Count the walls of type "type" contained in the current selection
void countwalls(int *type)
@@ -338,6 +564,46 @@
         }
     }
}
+
+int getcurtex(const char* pos, const char* x, const char* y); //prototype
+
+void tex2front(const char* pos)
+{
+    if (noselection())
+    return;
+
+    int t = -1; //type (position)
+
+    if (strcmp(pos, "FLOOR") == 0) t = 0;
+    else if (strcmp(pos, "WALL") == 0) t = 1;
+    else if (strcmp(pos, "UPWALL") == 0) t = 3;
+    else if (strcmp(pos, "CEIL") == 0) t = 2;
+    else
+    {
+        conoutf("\f9ERROR: \f5invalid position argument");
+        return;
+    }
+
+    if (t == 3) t = 1; //walls
+
+    int key = getcurtex(pos, "", "");
+    //conoutf("Key is texture slot %i", key);
+    //conoutf("Searching edit texture lists for match...");
+
+    loopi(255)
+    {
+        if (hdr.texlists[t][i] == key)
+        {
+            //conoutf("Match found in position: %i", i);
+            curedittex[t] = i;
+            break;
+        }
+    }
+
+    tofronttex();
+}
+
+COMMAND (tex2front, "s");

void editdrag(bool isdown)
{
@@ -454,6 +720,1002 @@
         addmsg(SV_EDITT, "ri6", sels[i].x, sels[i].y, sels[i].xs, sels[i].ys, type, t);
     }
}
+
+int expandsel(int s) //makes all selections collections of 1 x 1 selections
+{
+    int count = 0; //number of cubes in selections to remove
+
+    int stop = sels.length();
+    int removed = 0;
+
+    for (int i = 0; i < stop; i++)
+    {
+        for (int y = sels[i].y; y < sels[i].y + sels[i].ys; y++) //y loop
+        for (int x = sels[i].x; x < sels[i].x + sels[i].xs; x++) //x loop
+        {
+            addselection(x, y, 1, 1, sels[i].h);
+
+            if (i >= stop - s) //selections to remove
+            count++;
+        }
+
+        sels.remove(i);
+        i--;
+        stop--;
+        removed++;
+    }
+
+
+    return count;
+}
+
+void compress_sel(int s) //combines adjacent selections (1 x 1 selections only)
+{
+    EDITSEL;
+
+    int min_x = 0;
+    int min_y = 0;
+
+    int max_x = 0;
+    int max_y = 0;
+    int max_h = 0;
+
+    int x;
+    int y;
+    int h;
+
+    /** Initialize selections map **/
+
+    loopv(sels)
+    {
+        if (i == 0) //initialize bounds
+        {
+            min_x = sels[i].x + sels[i].xs;
+            max_x = sels[i].x + sels[i].xs;
+            min_y = sels[i].y + sels[i].ys;
+            max_y = sels[i].y + sels[i].ys;
+            max_h = sels[i].h;
+        }
+
+        x = sels[i].x + sels[i].xs;
+        y = sels[i].y + sels[i].ys;
+        h = sels[i].h;
+
+        if (x < min_x) min_x = x;
+
+        if (x > max_x) max_x = x;
+
+        if (y < min_y) min_y = y;
+
+        if (y > max_y) max_y = y;
+
+        if (h > max_h) max_h = h;
+    }
+
+    bool cubemap [2 + (max_y - min_y)][2 + (max_x - min_x)];
+    memset(cubemap, false, sizeof(cubemap));
+
+    for(int i = 0; i<sels.length(); i++)
+    {
+        if (i < sels.length()-s)
+        cubemap[sels[i].y + sels[i].ys - min_y] [sels[i].x + sels[i].xs - min_x] = true;
+        else
+        cubemap[sels[i].y + sels[i].ys - min_y] [sels[i].x + sels[i].xs - min_x] = false;
+    }
+
+    /** reselect rows of cubes according to map **/
+
+    resetselections();
+
+    int slice_start; //first cube in a horizontal selection slice
+
+    for (y = 0; y < (max_y - min_y) + 1; y++)
+    {
+        slice_start = -1;
+
+        for (x = 0; x < (max_x - min_x) + 1; x++)
+        {
+            if (cubemap[y][x])
+            {
+                if (slice_start < 0)
+                slice_start = x;
+            }
+            else
+            {
+                if (slice_start > -1)
+                addselection(min_x + slice_start - 1, min_y + y - 1, x - slice_start, 1, max_h);
+
+                slice_start = -1;
+                continue;
+            }
+
+            if ((x + 1 >= (max_x - min_x) + 1) && slice_start > -1)
+            addselection(min_x + slice_start - 1, min_y + y - 1, x - slice_start + 1, 1, max_h);
+        }
+    }
+
+    /** combine rows of equal length vertically adjacent to each other **/
+
+    int y2;
+
+    loopv (sels) //i loop
+    loopvj (sels) //j loop
+    {
+        if (sels[i].x == sels[j].x) //same x coordinate
+        if (sels[i].y == sels[j].y + sels[j].ys || sels[j].y == sels[i].y + sels[i].ys) //vertically adjacent
+        if (sels[i].xs == sels[j].xs) //same length
+        {
+            min_y = sels[i].y;
+            max_y = sels[i].y + sels[i].ys;
+            max_h = sels[i].h;
+
+            y = sels[j].y;
+            y2 = sels[j].y + sels[j].ys;
+            h = sels[j].h;
+
+            if (y < min_y) min_y = y;
+            if (y > max_y) max_y = y;
+            if (y2 < min_y) min_y = y2;
+            if (y2 > max_y) max_y = y2;
+            if (h > max_h) max_h = h;
+
+            addselection(sels[i].x, min_y, sels[i].xs, max_y - min_y, max_h);
+
+            sels.remove(i);
+
+            if (i < j)  //if deleting i offset j
+            sels.remove(j - 1);
+            else
+            sels.remove(j);
+
+            i = 0;
+            break; //exit this j loop, go to next j loop, of i loop
+        }
+    }
+}
+
+void fixselh ()
+{
+    bool fc;
+
+    if (flrceil == 0) fc = false; //floor
+    else fc = true;
+
+    sqr *s1;
+    sqr *s2;
+
+    loopv (sels)
+    {
+        s1 = S(sels[i].x, sels[i].y);
+        s2 = S(sels[i].x + sels[i].xs - 1, sels[i].y + sels[i].ys - 1);
+
+        if(!fc) //finding max floor height
+        {
+            if (s1->floor > s2->floor)
+            sels[i].h = s1->floor;
+            else
+            sels[i].h = s2->floor;
+        }
+        else //finding max ceiling height
+        {
+            if (s1->ceil > s2->ceil)
+            sels[i].h = s1->ceil;
+            else
+            sels[i].h = s2->ceil;
+        }
+    }
+}
+
+/** expand selections and select only selections matching argument keys **/
+
+void filter_sel(const char* type, char* v1, char* v2, char* v3, char* v4, char* v5, char* v6, char* v7)
+{
+    EDITSEL;
+
+    /** Process filter type **/
+
+    int filter_type = 0;
+
+    if (strcmp(type, "FLOOR_T") == 0) filter_type = 1;
+    if (strcmp(type, "WALL_T") == 0) filter_type = 2;
+    if (strcmp(type, "UPWALL_T") == 0) filter_type = 3;
+    if (strcmp(type, "CEIL_T") == 0) filter_type = 4;
+    if (strcmp(type, "FLOOR_H") == 0) filter_type = 5;
+    if (strcmp(type, "CEIL_H") == 0) filter_type = 6;
+    if (strcmp(type, "DISSOLVE") == 0) filter_type = 7;
+    if (strcmp(type, "SOLID") == 0) filter_type = 8;
+    if (strcmp(type, "HEIGHTFIELD") == 0) filter_type = 9;
+    if (strcmp(type, "CORNER") == 0) filter_type = 10;
+    if (strcmp(type, "SPACE") == 0) filter_type = 11;
+    if (strcmp(type, "SUBTRACT") == 0) filter_type = 12;
+    if (strcmp(type, "MERGE") == 0) filter_type = 13;
+
+    if (filter_type == 0)
+    {
+        conoutf("\f9ERROR: \f5invalid filter type");
+        return;
+    }
+
+    /** Count value arguments **/
+
+    int num_v = 0;
+
+    if (strcmp(v1, "") != 0) num_v++;
+
+    if (strcmp(v2, "") != 0) num_v++;
+
+    if (strcmp(v3, "") != 0) num_v++;
+
+    if (strcmp(v4, "") != 0) num_v++;
+
+    if (strcmp(v5, "") != 0) num_v++;
+
+    if (strcmp(v6, "") != 0) num_v++;
+
+    if (strcmp(v7, "") != 0) num_v++;
+
+    if (num_v < 1 && filter_type != 12 && filter_type != 13)
+    {
+        conoutf("\f9ERROR: \f5this filter requires at least one key value");
+        return;
+    }
+
+    int v [num_v];
+
+    if (num_v > 0) v[0] = atoi(v1);
+    if (num_v > 1) v[1] = atoi(v2);
+    if (num_v > 2) v[2] = atoi(v3);
+    if (num_v > 3) v[3] = atoi(v4);
+    if (num_v > 4) v[4] = atoi(v5);
+    if (num_v > 5) v[5] = atoi(v6);
+    if (num_v > 6) v[6] = atoi(v7);
+
+    int count = 0;
+
+    if (strcmp(v1, "") != 0)
+    count = expandsel(v[0]); //expand selections to 1 x 1 selections
+    else
+    count = expandsel(1);
+
+    /** filter selection(s) */
+
+    bool match; //match found
+
+    loopv(sels)
+    {
+        sqr *s = S((sels[i]).x, (sels[i]).y);
+        match = false;
+
+        switch(filter_type)
+        {
+            case 1: //floor texture
+            loopj (num_v)
+            {
+                if (s->ftex == v[j])
+                {
+                    match = true;
+                    break;
+                }
+            }
+
+            //no match by end of iteration
+
+            if (!match)
+            {
+                sels.remove(i);
+                i--;
+            }
+
+            break;
+
+            case 2: //wall texture
+            loopj (num_v)
+            {
+                if (s->wtex == v[j])
+                {
+                    match = true;
+                    break;
+                }
+            }
+
+            //no match by end of iteration
+
+            if (!match)
+            {
+                sels.remove(i);
+                i--;
+            }
+
+            break;
+
+            case 3: // upper wall texture
+            loopj (num_v)
+            {
+                if (s->utex == v[j])
+                {
+                    match = true;
+                    break;
+                }
+            }
+
+            //no match by end of iteration
+
+            if (!match)
+            {
+                sels.remove(i);
+                i--;
+            }
+
+            break;
+
+            case 4: //ceiling texture
+            loopj (num_v)
+            {
+                if (s->ctex == v[j])
+                {
+                    match = true;
+                    break;
+                }
+            }
+
+            //no match by end of iteration
+
+            if (!match)
+            {
+                sels.remove(i);
+                i--;
+            }
+
+            break;
+
+            case 5: //floor height
+            loopj (num_v)
+            {
+                if (s->floor == v[j])
+                {
+                    match = true;
+                    break;
+                }
+            }
+
+            //no match by end of iteration
+
+            if (!match)
+            {
+                sels.remove(i);
+                i--;
+            }
+
+            break;
+
+            case 6: //ceiling height
+            loopj (num_v)
+            {
+                if (s->ceil == v[j])
+                {
+                    match = true;
+                    break;
+                }
+            }
+
+            //no match by end of iteration
+
+            if (!match)
+            {
+                sels.remove(i);
+                i--;
+            }
+
+            break;
+
+            case 7: //dissolve
+            if (1 + rand()%99 < v[0]) //frequency
+            {
+                sels.remove(i);
+                i--;
+            }
+            break;
+
+            case 8: //solid
+            if (v[0] < 1) //if / if not
+            {
+                if (s->type == SOLID)
+                {
+                    sels.remove(i);
+                    i--;
+                }
+            }
+            else if (s->type != SOLID)
+            {
+                sels.remove(i);
+                i--;
+            }
+            break;
+
+            case 9: //heightfield
+            if (v[0] < 1) //if / if not
+            {
+                if (s->type == FHF || s->type == CHF)
+                {
+                    sels.remove(i);
+                    i--;
+                }
+            }
+            else if (s->type != FHF && s->type != CHF)
+            {
+                sels.remove(i);
+                i--;
+            }
+            break;
+
+            case 10: //corner
+            if (v[0] < 1) //if / if not
+            {
+                if (s->type == CORNER)
+                {
+                    sels.remove(i);
+                    i--;
+                }
+            }
+            else if (s->type != CORNER)
+            {
+                sels.remove(i);
+                i--;
+            }
+            break;
+
+            case 11: //space
+            if (v[0] < 1) //if / if not
+            {
+                if (s->type == SPACE)
+                {
+                    sels.remove(i);
+                    i--;
+                }
+            }
+            else if (s->type != SPACE)
+            {
+                sels.remove(i);
+                i--;
+            }
+            break;
+
+            default:
+            break;
+        }
+    }
+
+    if (!sels.empty()) //if there is a selection to simplify
+    {
+        if (filter_type == 12 && count > 0) //remove
+        compress_sel(count);
+        else
+        compress_sel(0);
+    }
+
+    fixselh();
+}
+
+COMMAND (filter_sel, "ssssssss");
+
+extern float Mh;
+
+void select_all()
+{
+    resetselections();
+    addselection(mapdims[0] - 1, mapdims[1] - 1, mapdims[2] - mapdims[0] + 3, mapdims[3] - mapdims[1] + 3, Mh);
+}
+
+COMMAND (select_all, "");
+
+struct Slot
+{
+    string name;
+    float scale;
+    Texture *tex;
+    bool loaded;
+};
+
+extern vector<Slot> slots;
+
+void texname(const char* pos)
+{
+    if (noselection())
+    {
+        result("first make a selection");
+        return;
+    }
+
+    sqr *s = 0; //cube
+    int t = -1; //type
+
+    /** get type to check **/
+
+    if (strcmp(pos, "FLOOR") == 0) t = 0;
+    else if (strcmp(pos, "WALL") == 0) t = 1;
+    else if (strcmp(pos, "UPWALL") == 0) t = 2;
+    else if (strcmp(pos, "CEIL") == 0) t = 3;
+    else
+    {
+        conoutf("\f9ERROR: \f5invalid position argument");
+        result("-1");
+        return;
+    }
+
+    s = S((sels[sels.length() - 1]).x, (sels[sels.length() - 1]).y);
+
+    if (!s)
+    {
+        result("error");
+        return;
+    }
+
+    switch (t)
+    {
+        case 0:
+        result(slots[s->ftex].tex->name);
+        break;
+
+        case 1:
+        result(slots[s->wtex].tex->name);
+        break;
+
+        case 2:
+        result(slots[s->utex].tex->name);
+        break;
+
+        case 3:
+        result(slots[s->ctex].tex->name);
+        break;
+
+        default:
+        result("error");
+    }
+}
+
+COMMAND(texname, "s");
+
+int getcurtex(const char* pos, const char* x, const char* y) //returns index of texture slot
+{
+    /** Count arguments **/
+    int num_args = 0;
+
+    if (strcmp(pos, "") != 0)
+    num_args++;
+
+    if (strcmp(x, "") != 0)
+    num_args++;
+
+    if (strcmp(y, "") != 0)
+    num_args++;
+
+    if (num_args == 1) //working from selection
+    {
+        if (noselection())
+        {
+            result("-1");
+            return -1;
+        }
+    }
+
+    if (num_args == 2)
+    {
+        conoutf("\f9ERROR: \f5missing Y argument");
+        result("-1");
+        return -1;
+    }
+
+    /**/
+
+    sqr *s = 0; //cube
+    int t = -1; //type
+
+    /** get type to check **/
+
+    if (strcmp(pos, "FLOOR") == 0) t = 0;
+    else if (strcmp(pos, "WALL") == 0) t = 1;
+    else if (strcmp(pos, "UPWALL") == 0) t = 2;
+    else if (strcmp(pos, "CEIL") == 0) t = 3;
+    else
+    {
+        conoutf("\f9ERROR: \f5invalid position argument");
+        result("-1");
+        return -1;
+    }
+
+    /**/
+
+    int X = atoi(x);
+    int Y = atoi(y);
+
+    switch (num_args)
+    {
+        case 1:
+        s = S((sels[sels.length() - 1]).x, (sels[sels.length() - 1]).y);
+        break;
+
+        case 3:
+        if (OUTBORD(X, Y))
+        {
+            conoutf("\f9ERROR: \f5coordinates out of bounds");
+            result("-1");
+            return -1;
+        }
+        s = S(X, Y);
+        break;
+
+        default:
+        result("-1");
+        return -1;
+    }
+
+    string buf = "";
+
+    switch (t)
+    {
+        case 0:
+        concatformatstring(buf, "%d ", s->ftex);
+        result(buf);
+        return s->ftex;
+
+        case 1:
+        concatformatstring(buf, "%d ", s->wtex);
+        result(buf);
+        return s->wtex;
+
+        case 2:
+        concatformatstring(buf, "%d ", s->utex);
+        result(buf);
+        return s->utex;
+
+        case 3:
+        concatformatstring(buf, "%d ", s->ctex);
+        result(buf);
+        return s->ctex;
+
+        default:
+        result("-1");
+        return -1;
+    }
+
+    result("-1");
+    return -1;
+}
+
+void curtex(const char* pos, const char* x, const char* y) //prints texture slot info
+{
+    /** Count arguments **/
+
+    int num_args = 0;
+
+    if (strcmp(pos, "") != 0)
+    num_args++;
+
+    if (strcmp(x, "") != 0)
+    num_args++;
+
+    if (strcmp(y, "") != 0)
+    num_args++;
+
+    if (num_args < 2) //working from selection
+    {
+        if (noselection())
+        return;
+    }
+
+    if (num_args == 2)
+    {
+        conoutf("\f9ERROR: \f5missing Y argument");
+        return;
+    }
+
+    /**/
+
+    sqr *s = 0; //cube
+    int t = -1; //type
+
+    /** get type to check **/
+
+    if (strcmp(pos, "FLOOR") == 0) t = 0;
+    else if (strcmp(pos, "WALL") == 0) t = 1;
+    else if (strcmp(pos, "UPWALL") == 0) t = 2;
+    else if (strcmp(pos, "CEIL") == 0) t = 3;
+    else if (strcmp(pos, "ALL") == 0 || num_args == 0) t = 4;
+    else
+    {
+        conoutf("\f9ERROR: \f5invalid position argument");
+        return;
+    }
+
+    /**/
+
+    int X = atoi(x);
+    int Y = atoi(y);
+
+    switch (num_args)
+    {
+        case 0:
+        case 1:
+        s = S((sels[sels.length() - 1]).x, (sels[sels.length() - 1]).y);
+        break;
+
+        case 3:
+
+        if (OUTBORD(X, Y))
+        {
+            conoutf("\f9ERROR: \f5coordinates out of bounds");
+            return;
+        }
+        s = S(X, Y);
+        break;
+
+        default:
+        return;
+    }
+
+    switch (t)
+    {
+        case 0:
+        conoutf("The \fPfloor \f5texture of this cube is slot number \fN%i", s->ftex);
+        conoutf("\fM--------------------------------------------------------------");
+        break;
+
+        case 1:
+        conoutf("The \fPwall \f5texture of this cube is slot number \fN%i", s->wtex);
+        conoutf("\fM--------------------------------------------------------------");
+        break;
+
+        case 2:
+        conoutf("The \fPupper wall \f5texture of this cube is slot number \fN%i", s->utex);
+        conoutf("\fM--------------------------------------------------------------");
+        break;
+
+        case 3:
+        conoutf("The \fPceiling \f5texture of this cube is slot number \fN%i", s->ctex);
+        conoutf("\fM--------------------------------------------------------------");
+        break;
+
+        case 4:
+        conoutf("The \fPfloor \f5texture of this cube is slot number \fN%i", s->ftex);
+        conoutf("The \fPwall \f5texture of this cube is slot number \fN%i", s->wtex);
+        conoutf("The \fPupper wall \f5texture of this cube is slot number \fN%i", s->utex);
+        conoutf("The \fPceiling \f5texture of this cube is slot number \fN%i", s->ctex);
+        conoutf("\fM--------------------------------------------------------------");
+
+        default:
+        return;
+    }
+}
+
+COMMAND(curtex, "sss");
+COMMAND(getcurtex, "sss");
+
+int getcurheight(const char* pos, const char* x, const char* y) //returns height of cubes
+{
+    /** Count arguments **/
+    int num_args = 0;
+
+    if (strcmp(pos, "") != 0)
+    num_args++;
+
+    if (strcmp(x, "") != 0)
+    num_args++;
+
+    if (strcmp(y, "") != 0)
+    num_args++;
+
+    if (num_args < 2) //working from selection
+    {
+        if (noselection())
+        {
+            result("-255");
+            return -255;
+        }
+
+        if (num_args == 0)
+        {
+            conoutf("\f9ERROR: \f5getcurheight cannot be called with no arguments");
+            result("-255");
+            return -255;
+        }
+    }
+
+    if (num_args == 2)
+    {
+        conoutf("\f9ERROR: \f5missing Y argument");
+        result("-255");
+        return -255;
+    }
+
+    /**/
+
+    sqr *s = 0; //cube
+    int p = -1; //position
+
+    /** get type to check **/
+
+    if (strcmp(pos, "FLOOR") == 0) p = 0;
+    else if (strcmp(pos, "CEIL") == 0) p = 1;
+    else
+    {
+        conoutf("\f9ERROR: \f5invalid position argument");
+        result("-255");
+        return -255;
+    }
+
+    /** Grab cube **/
+
+    int X = atoi(x);
+    int Y = atoi(y);
+
+    switch (num_args)
+    {
+        case 1:
+        s = S((sels[sels.length() - 1]).x, (sels[sels.length() - 1]).y);
+        break;
+
+        case 3:
+        if (OUTBORD(X, Y))
+        {
+            conoutf("\f9ERROR: \f5coordinates out of bounds");
+            result("-255");
+            return -255;
+        }
+        s = S(X, Y);
+        break;
+
+        default:
+        result("-255");
+        return -255;
+    }
+
+    /** get height **/
+
+    string buf = "";
+
+    switch (p)
+    {
+        case 0:
+        concatformatstring(buf, "%d ", s->floor);
+        result(buf);
+        return s->floor;
+
+        case 1:
+        concatformatstring(buf, "%d ", s->ceil);
+        result(buf);
+        return s->ceil;
+
+        default:
+        result("-255");
+        return -255;
+    }
+
+    result("-255");
+    return -255;
+}
+
+void curheight(const char* pos, const char* x, const char* y) //prints height of cubes
+{
+    /** Count arguments **/
+    int num_args = 0;
+
+    if (strcmp(pos, "") != 0)
+    num_args++;
+
+    if (strcmp(x, "") != 0)
+    num_args++;
+
+    if (strcmp(y, "") != 0)
+    num_args++;
+
+    if (num_args < 2) //working from selection
+    {
+        if (noselection())
+        return;
+    }
+
+    if (num_args == 2)
+    {
+        conoutf("\f9ERROR: \f5missing Y argument");
+        return;
+    }
+
+    /**/
+
+    sqr *s = 0; //cube
+    int p = -1; //position
+
+    /** get type to check **/
+
+    if (strcmp(pos, "FLOOR") == 0) p = 0;
+    else if (strcmp(pos, "CEIL") == 0) p = 1;
+    else if (num_args == 0 || strcmp(pos, "BOTH") == 0) p = 2;
+    else
+    {
+        conoutf("\f9ERROR: \f5invalid position argument");
+        return;
+    }
+
+    /** Grab cube **/
+
+    int X = atoi(x);
+    int Y = atoi(y);
+
+    switch (num_args)
+    {
+        case 0:
+        case 1:
+        s = S((sels[sels.length() - 1]).x, (sels[sels.length() - 1]).y);
+        break;
+
+        case 3:
+        if (OUTBORD(X, Y))
+        {
+            conoutf("\f9ERROR: \f5coordinates out of bounds");
+            return;
+        }
+        s = S(X, Y);
+        break;
+
+        default:
+        return;
+    }
+
+    /** get height **/
+
+    switch (p)
+    {
+        case 0:
+        conoutf("The \fPfloor \f5height of this cube is \fN%i", s->floor);
+        conoutf("\fM--------------------------------------------------------------");
+        break;
+
+        case 1:
+        conoutf("The \fPceiling \f5height of this cube is \fN%i", s->ceil);
+        conoutf("\fM--------------------------------------------------------------");
+        break;
+
+        case 2:
+        conoutf("The \fPfloor \f5height of this cube is \fN%i", s->floor);
+        conoutf("The \fPceiling \f5height of this cube is \fN%i", s->ceil);
+        conoutf("\fM--------------------------------------------------------------");
+
+        default:
+        return;
+    }
+}
+
+COMMAND(getcurheight, "sss");
+COMMAND(curheight, "sss");
+
+void undo_sel(char* n) //removes last selection
+{
+    if (sels.empty())
+    {
+        conoutf("no selections to remove");
+        return;
+    }
+
+    int num;
+
+    if (strcmp(n, "") != 0) num = atoi(n);
+    else
+    num = 1;
+
+    while (num > 0)
+    {
+        if (sels.empty())
+        {
+            conoutf("no more selections to remove");
+            return;
+        }
+
+        sels.pop();
+        num--;
+    }
+}
+
+COMMAND (undo_sel, "s");

void replace()
{
@@ -528,6 +1790,42 @@
}

COMMAND(equalize, "i");
+
+void equalize_sels(int *flr) //equalizes *all* sels instead of *each* sel
+{
+    bool isfloor = *flr==0;
+    EDITSEL;
+
+    int hi = 0;
+    int low = 0;
+
+    loopv(sels) //collect min/max info
+    {
+        block &sel = sels[i];
+
+        loopselxy(sel,
+        {
+            if(s->floor<low) low = s->floor;
+            if(s->ceil>hi) hi = s->ceil;
+        });
+    }
+
+    loopv(sels) //height asignments
+    {
+        block &sel = sels[i];
+
+        loopselxy(sel,
+        {
+            if(isfloor) s->floor = low; else s->ceil = hi;
+            if(s->floor>=s->ceil) s->floor = s->ceil-1;
+        });
+
+        addmsg(SV_EDITE, "ri5", sel.x, sel.y, sel.xs, sel.ys, isfloor);
+    }
+
+}
+
+COMMAND(equalize_sels, "i");

void setvdeltaxy(int delta, block &sel)
{
--- entities.cpp    Tue Oct 22 13:57:16 2013
+++ entities.cpp    Fri May 23 02:52:06 2014
@@ -3,7 +3,9 @@
#include "cube.h"

VAR(showclips, 0, 1, 1);
-VAR(showmodelclipping, 0, 0, 1);
+VAR(showmodelclipping, 0, 0, 1);
+
+extern bool cleanedit;

vector<entity> ents;
vector<int> eh_ents; // edithide entities
@@ -26,7 +28,10 @@
  }

void renderclip(entity &e)
-{
+{
+    if (cleanedit)
+    return;
+
     float xradius = max(float(e.attr2), 0.1f), yradius = max(float(e.attr3), 0.1f);
     vec bbmin(e.x - xradius, e.y - yradius, float(S(e.x, e.y)->floor+e.attr1)),
         bbmax(e.x + xradius, e.y + yradius, bbmin.z + max(float(e.attr4), 0.1f));
@@ -124,7 +129,10 @@
COMMAND(seteditshow, "s");

void renderentarrow(const entity &e, const vec &dir, float radius)
-{
+{
+    if (cleanedit)
+    return;
+
     if(radius <= 0) return;
     float arrowsize = min(radius/8, 0.5f);
     vec epos(e.x, e.y, e.z);
@@ -153,11 +161,13 @@
     glEnable(GL_CULL_FACE);
     glEnable(GL_TEXTURE_2D);
}
+
+extern int globalfps;

void renderentities()
{
     int closest = editmode ? closestent() : -1;
-    if(editmode && !reflecting && !refracting && !stenciling)
+    if(editmode && !reflecting && !refracting && !stenciling && !cleanedit)
     {
         static int lastsparkle = 0;
         if(lastmillis - lastsparkle >= 20)
@@ -174,29 +184,49 @@
                 vec v(e.x, e.y, e.z);
                 if(vec(v).sub(camera1->o).dot(camdir) < 0) continue;
                 //particle_splash(i == closest ? PART_ELIGHT : PART_ECLOSEST, 2, 40, v);
-                int sc = PART_ECARROT; // "carrot" (orange) - entity slot currently unused, possibly "reserved"
+                int sc = PART_ELIGHT;
                 if(i==closest)
                 {
-                    sc = PART_ECLOSEST; // blue
-                }
-                else switch(e.type)
+                    sc = PART_ECLOSEST; // smoke
+                    particle_splash(PART_ECLOSEST, 1, 80, v);
+                }
+
+                switch(e.type)
                 {
-                    case LIGHT : sc = PART_ELIGHT; break; // white
-                    case PLAYERSTART: sc = PART_ESPAWN; break; // green
+                    case LIGHT : sc = PART_ELIGHT; break; // white
+
+                    case PLAYERSTART:
+                    if (e.attr2 == 0)
+                    {sc = PART_RED; break;} // CLA
+                    else if (e.attr2 == 1)
+                    {sc = PART_BLUE; break;} // RVSF
+                    else
+                    sc = PART_GREEN; break; // FFA
+
                     case I_CLIPS:
-                    case I_AMMO:
-                    case I_GRENADE: sc = PART_EAMMO; break; // red
+                    case I_AMMO:
+                    case I_AKIMBO:
+                    case I_GRENADE: sc = PART_EAMMO; break; // orange
                     case I_HEALTH:
                     case I_HELMET:
-                    case I_ARMOUR:
-                    case I_AKIMBO: sc = PART_EPICKUP; break; // yellow
-                    case MAPMODEL:
-                    case SOUND: sc = PART_EMODEL; break; // magenta
-                    case LADDER:
-                    case CLIP:
-                    case PLCLIP: sc = PART_ELADDER; break; // grey
-                    case CTF_FLAG: sc = PART_EFLAG; break; // turquoise
-                    default: break;
+                    case I_ARMOUR: sc = PART_EPICKUP; break; // yellow
+                    case MAPMODEL: sc = PART_EMODEL; break; // magenta
+                    case LADDER: sc = PART_ELADDER; break; // grey
+
+                    case CLIP: sc = PART_CLIP; break; // yellow (color of the clip)
+                    case PLCLIP: sc = PART_PLCLIP; break; // magenta (color of the clip)
+
+                    case CTF_FLAG:
+                    if (e.attr2 == 0) // CLA
+                    {sc = PART_RED; break;}
+                    else if (e.attr2 == 1) // RVSF
+                    {sc = PART_BLUE; break;}
+                    else
+                    {sc = PART_ELIGHT; break;}
+
+                    default: break;
+
+                    case SOUND: sc = 22; break; // cyan
                 }
                 //particle_splash(sc, i==closest?6:2, i==closest?120:40, v);
                 particle_splash(sc, 2, 40, v);
@@ -240,8 +270,14 @@
             switch(e.type)
             {
                 case PLAYERSTART:
-                {
-                    glColor3f(0, 1, 1);
+                {
+                    if (e.attr2 == 0)
+                    glColor3f(1, 0, 0); // CLA
+                    else if (e.attr2 == 1)
+                    glColor3f(0, 0, 1); // RVSF
+                    else
+                    glColor3f(0, 1, 0); // FFA
+
                     vec dir;
                     vecfromyawpitch(e.attr1, 0, -1, 0, dir);
                     renderentarrow(e, dir, 4);
--- main.cpp    Tue Oct 29 04:33:15 2013
+++ main.cpp    Mon May 19 23:38:43 2014
@@ -1280,7 +1280,9 @@
         serverslice(0);

         if(elapsed) fps = (1000.0f/elapsed+fps*10)/11; // avoid DIV-by-0
-        frames++;
+        frames++;
+
+        globalfps = fps;

         audiomgr.updateaudio();

@@ -1322,4 +1324,4 @@
}

VAR(version, 1, AC_VERSION, 0);
-VAR(protocol, 1, PROTOCOL_VERSION, 0);
\ No newline at end of file
+VAR(protocol, 1, PROTOCOL_VERSION, 0);
--- Makefile    Sat Nov 09 18:12:11 2013
+++ Makefile    Wed Apr 16 20:37:19 2014
@@ -1,6 +1,12 @@
-CXXFLAGS= -O3 -fomit-frame-pointer
-CXX=clang++    # Use clang++, as g++ optimizations cause crashes...
-override CXXFLAGS+= -Wall -fsigned-char
+
+
+CXXFLAGS= -O3 -fomit-frame-pointer -Wno-unused-variable
+ifneq (,$(findstring MINGW,$(PLATFORM)))
+  CXXFLAGS+= -Wall -fsigned-char
+else
+  CXX=clang++   # Use clang++, as g++ optimizations cause crashes...
+  override CXXFLAGS+= -Wall -fsigned-char
+endif

PLATFORM= $(shell uname -s)
PLATFORM_PREFIX=native
@@ -392,3 +398,4 @@
master-standalone.o: cube.h platform.h tools.h geom.h model.h protocol.h
master-standalone.o: sound.h weapon.h entity.h world.h i18n.h command.h
master-standalone.o: varray.h vote.h console.h protos.h
+
--- physics.cpp    Tue Oct 22 13:57:19 2013
+++ physics.cpp    Thu May 22 20:37:00 2014
@@ -474,7 +474,7 @@
                     }
                 }

-                if(timeinair > 200 && !pl->timeinair)
+                if(timeinair > 200 && !pl->timeinair && !water)
                 {
                     int sound = timeinair > 800 ? S_HARDLAND : S_SOFTLAND;
                     if(pl->state!=CS_DEAD)
--- protos.h    Sat Nov 09 13:48:58 2013
+++ protos.h    Fri May 23 02:52:10 2014
@@ -496,7 +496,8 @@
extern void removedynlights(physent *owner);
extern block *blockcopy(const block &b);
extern void blockpaste(const block &b, int bx, int by, bool light);
-extern void blockpaste(const block &b);
+extern void blockpaste(const block &b);
+extern void halfblockpaste(const block &b, int bx, int by, bool floor);
extern void freeblock(block *&b);

// worldrender
@@ -626,7 +627,7 @@
{
     PART_SPARK = 0,
     PART_SMOKE,
-    PART_ECLOSEST,
+    PART_BLUE,
     PART_BLOOD,
     PART_DEMOTRACK,
     PART_FIREBALL,
@@ -637,13 +638,16 @@
     PART_HUDMUZZLEFLASH,
     PART_MUZZLEFLASH,
     PART_ELIGHT,
-    PART_ESPAWN,
-    PART_EAMMO,
+    PART_GREEN,
+    PART_RED,
     PART_EPICKUP,
     PART_EMODEL,
-    PART_ECARROT,
+    PART_EAMMO,
     PART_ELADDER,
-    PART_EFLAG
+    PART_ECLOSEST,
+    PART_SOUND = 22,
+    PART_CLIP,
+    PART_PLCLIP
};

extern void particleinit();
--- renderhud.cpp    Tue Oct 22 13:57:19 2013
+++ renderhud.cpp    Sat Jun 07 00:20:51 2014
@@ -1,6 +1,8 @@
// renderhud.cpp: HUD rendering

#include "cube.h"
+
+extern bool cleanedit;

void drawicon(Texture *tex, float x, float y, float s, int col, int row, float ts)
{
@@ -278,7 +280,10 @@
COMMAND(loadcrosshair, "ss");

void drawcrosshair(playerent *p, int n, color *c, float size)
-{
+{
+    if (cleanedit && editmode)
+    return;
+
     Texture *crosshair = crosshairs[n];
     if(!crosshair)
     {
@@ -890,7 +895,22 @@
     char *infostr = editinfo();
     int commandh = 1570 + FONTH;
     if(command) commandh -= rendercommand(20, 1570, VIRTW);
-    else if(infostr) draw_text(infostr, 20, 1570);
+
+    else if(infostr)
+    {
+        if (cleanedit)
+        {
+            glPushMatrix();
+            glLoadIdentity();
+            glOrtho(0, VIRTW*2, VIRTH*2, 0, -1, 1);
+            glScalef(1.0, 1.0, 1.0); //set scale
+            draw_text(infostr, 48, VIRTH*2 -4*FONTH);
+            glPopMatrix();
+        }
+        else
+        draw_text(infostr, 20, 1570);
+    }
+
     else if(targetplayer && showtargetname) draw_text(colorname(targetplayer), 20, 1570);
     glLoadIdentity();
     glOrtho(0, VIRTW*2, VIRTH*2, 0, -1, 1);
--- renderparticles.cpp    Tue Oct 22 13:57:19 2013
+++ renderparticles.cpp    Fri May 23 02:58:31 2014
@@ -184,7 +184,7 @@
     }
}

-#define MAXPARTYPES 22
+#define MAXPARTYPES 25

struct particle { vec o, d; int fade, type; int millis; particle *next; };
particle *parlist[MAXPARTYPES], *parempty = NULL;
@@ -252,7 +252,7 @@
{
     { PT_PART,       0.4f, 0.4f, 0.4f, 2,  0, 0.06f }, // yellow: sparks
     { PT_PART,       1.0f, 1.0f, 1.0f, 20, 1, 0.15f }, // grey:   small smoke
-    { PT_PART,       0.0f, 0.0f, 1.0f, 20, 0, 0.08f }, // blue:   edit mode closest ent
+    { PT_PART,       0.0f, 0.0f, 1.0f, 20, 0, 0.08f }, // blue:   used for RVSF related entities
     { PT_BLOOD,      0.5f, 0.0f, 0.0f, 1,  4, 0.3f  }, // red:    blood spats
     { PT_PART,       1.0f, 0.1f, 0.1f, 0,  1, 0.2f  }, // red:    demotrack
     { PT_FIREBALL,   1.0f, 0.5f, 0.5f, 0,  2, 7.0f  }, // explosion fireball
@@ -264,16 +264,19 @@
     { PT_HUDFLASH,   1.0f, 1.0f, 1.0f, 0,  6, 0.7f  }, // hudgun muzzle flash
     { PT_FLASH,      1.0f, 1.0f, 1.0f, 0,  6, 0.7f  }, // muzzle flash
     { PT_PART,       1.0f, 1.0f, 1.0f, 20, 0, 0.08f }, // white: edit mode ent type : light
-    { PT_PART,       0.0f, 1.0f, 0.0f, 20, 0, 0.08f }, // green: edit mode ent type : spawn
-    { PT_PART,       1.0f, 0.0f, 0.0f, 20, 0, 0.08f }, // red: edit mode ent type : ammo
-    { PT_PART,       1.0f, 1.0f, 0.0f, 20, 0, 0.08f }, // yellow: edit mode ent type : pickup
-    { PT_PART,       1.0f, 0.0f, 1.0f, 20, 0, 0.08f }, // magenta: edit mode ent type : model, sound
-    { PT_PART,       1.0f, 0.5f, 0.2f, 20, 0, 0.08f }, // orange: edit mode ent type : "carrot"
-    { PT_PART,       0.5f, 0.5f, 0.5f, 20, 0, 0.08f }, // grey: edit mode ent type : ladder, (pl)clip
-    { PT_PART,       0.0f, 1.0f, 1.0f, 20, 0, 0.08f }, // turquoise: edit mode ent type : CTF-flag
+    { PT_PART,       0.0f, 1.0f, 0.0f, 20, 0, 0.08f }, // green: edit mode ent type : FFA spawn
+    { PT_PART,       1.0f, 0.0f, 0.0f, 20, 0, 0.08f }, // red: used for CLA related entities
+    { PT_PART,       0.78f, 1.0f, 0.33f, 20, 0, 0.08f }, // yellow-green: edit mode ent type : pickup
+    { PT_PART,       0.6f, 0.3f, 0.9f, 20, 0, 0.08f }, // purple: edit mode ent type : mapmodel
+    { PT_PART,       1.0f, 0.5f, 0.2f, 20, 0, 0.08f }, // orange: edit mode ent type : ammo
+    { PT_PART,       0.7f, 1.0f, 1.0f, 20, 0, 0.08f }, // bright cyan: edit mode ent type : ladder,
+    { PT_PART,       0.45f, 0.45f, 0.45f, 20, 1, 0.2f }, // smoke effect: closest/selected entity
     // 2011jun18 : shotty decals
     { PT_BULLETHOLE, 0.2f, 0.2f, 1.0f, 0,  3, 0.1f  }, // hole decal M
-    { PT_BULLETHOLE, 0.2f, 1.0f, 0.2f, 0,  3, 0.1f  }, // hole decal C
+    { PT_BULLETHOLE, 0.2f, 1.0f, 0.2f, 0,  3, 0.1f  }, // hole decal C
+    { PT_PART,       0.0f, 1.0f, 1.0f, 20, 0, 0.08f }, // cyan: edit mode ent type: sound
+    { PT_PART,       1.0f, 1.0f, 0.0f, 20, 0, 0.08f }, // yellow: edit mode ent type: clip
+    { PT_PART,       1.0f, 0.0f, 1.0f, 20, 0, 0.08f } // magenta: edit mode ent type: plclip
};

VAR(particlesize, 20, 100, 500);
--- tools.h    Tue Oct 22 13:57:19 2013
+++ tools.h    Wed Apr 02 10:50:08 2014
@@ -424,7 +424,7 @@

     T &pop() { return buf[--ulen]; }
     T &last() { return buf[ulen-1]; }
-    void drop() { buf[--ulen].~T(); }
+    void drop() { buf[--ulen].~T();}
     bool empty() const { return ulen==0; }

     int capacity() const { return alen; }
--- world.cpp    Tue Oct 22 13:57:19 2013
+++ world.cpp    Tue May 20 19:12:15 2014
@@ -127,10 +127,24 @@

COMMAND(nextclosestent, "");
COMMAND(closestenttype, "s");
+
+int active_ent = -1;
+bool locking_ent = false, lockselent = false;
+
+COMMANDF(togglelockselent, "", (void) { active_ent = -1; lockselent = !lockselent; if (lockselent) locking_ent = true;});

int closestent()        // used for delent and edit mode ent display
{
-    if(noteditmode("closestent")) return -1;
+    if(noteditmode("closestent")) return -1;
+
+    if (lockselent && !locking_ent && active_ent != -1)
+    {
+        if (ents[active_ent].type != NOTUSED)
+        return active_ent;
+        else
+        lockselent = false;
+    }
+
     int best = -1, bcnt = 0;
     float bdist = 99999;
     loopj(3)
@@ -150,7 +164,15 @@
             {
                 if(ents[best].x == e.x && ents[best].y == e.y && ents[best].z == e.z)
                 {
-                    if(j == 2 && bcnt == clentsel) return i;
+                    if(j == 2 && bcnt == clentsel)
+                    {
+                        if (locking_ent)
+                        {
+                            active_ent = i;
+                            locking_ent = false;
+                        }
+                        return i;
+                    }
                     bcnt++;
                 }
             }
@@ -162,7 +184,14 @@
         }
         if(best < 0 || bcnt == 1) break;
         if(bcnt) clentsel %= bcnt;
-    }
+    }
+
+    if (locking_ent)
+    {
+        active_ent = best;
+        locking_ent = false;
+    }
+
     return best;
}

@@ -173,7 +202,16 @@
     entity &e = ents[n];
     switch(prop)
     {
-        case 0: e.attr1 += amount; break;
+        case 0:
+        if (e.type == MAPMODEL)
+        {
+            e.attr1 += amount*16;
+            while (e.attr1 > 360) e.attr1 -= 360;
+            while (e.attr1 < 0) e.attr1 += 360;
+        }
+        else e.attr1 += amount;
+        break;
+
         case 1: e.attr2 += amount; break;
         case 2: e.attr3 += amount; break;
         case 3: e.attr4 += amount; break;
@@ -371,6 +409,26 @@
}

COMMANDF(scalelights, "ii", (int *f, int *i) { scalelights(*f, *i); });
+
+void scalelight(int f, int intens)
+{
+    entity &e = ents[closestent()];
+    if(e.type!=LIGHT) return;
+
+    e.attr1 = e.attr1*f/100;
+    if(e.attr1<2) e.attr1 = 2;
+    if(e.attr1>32) e.attr1 = 32;
+
+    if(intens)
+    {
+        scalecomp(e.attr2, intens);
+        scalecomp(e.attr3, intens);
+        scalecomp(e.attr4, intens);
+    }
+    calclight();
+}
+
+COMMANDF(scalelight, "ii", (int *f, int *i) { scalelight(*f, *i); });

int findentity(int type, int index)
{
--- worldlight.cpp    Tue Oct 22 13:57:19 2013
+++ worldlight.cpp    Fri Apr 11 15:30:00 2014
@@ -369,6 +369,49 @@
{
     blockpaste(b, b.x, b.y, false);
}
+
+void halfblockpaste(const block &b, int bx, int by, bool floor)
+{
+    const sqr *q = (const sqr *)((&b)+1);
+    for(int y = by; y<b.ys+by; y++)
+    for(int x = bx; x<b.xs+bx; x++)
+    {
+        if (q->type == SOLID || q->type == CORNER ||
+        //don't override heightfields with space unnessesarily
+        (q->type == SPACE && ((floor && S(x,y)->type != CHF) || (!floor && S(x,y)->type != FHF))))
+
+        S(x,y)->type = q->type;
+
+        if (floor || q->type == SOLID)
+        {
+            if (q->type == FHF ||
+            S(x-1,y)->type == FHF ||
+            S(x,y-1)->type == FHF ||
+            S(x-1,y-1)->type == FHF)
+            //
+            {S(x,y)->type = q->type; S(x,y)->vdelta = q->vdelta;}
+
+            S(x,y)->floor = q->floor;
+            S(x,y)->wtex = q->wtex;
+            S(x,y)->ftex = q->ftex;
+        }
+        else
+        {
+            if (q->type == CHF ||
+            S(x-1,y)->type == CHF ||
+            S(x,y-1)->type == CHF ||
+            S(x-1,y-1)->type == CHF)
+            //
+            {S(x,y)->type = q->type; S(x,y)->vdelta = q->vdelta;}
+
+            S(x,y)->ceil = q->ceil;
+            S(x,y)->utex = q->utex;
+            S(x,y)->ctex = q->ctex;
+        }
+
+        q++;
+    }
+}

void freeblock(block *&b)
{

Linux and Mac ports needed.
Thanks given by:


Messages In This Thread
RE: [Download] 1.2 Mapping Client - by PhaNtom - 08 Jun 14, 09:02PM
RE: [Download] 1.2 Mapping Client - by MCS - 09 Jun 14, 02:38AM
RE: [Download] 1.2 Mapping Client - by MPx - 10 Jun 14, 01:35AM
RE: [Download] 1.2 Mapping Client - by PhaNtom - 10 Jun 14, 02:22AM
RE: [Download] 1.2 Mapping Client - by RKTnoob - 10 Jun 14, 01:40PM
RE: [Download] 1.2 Mapping Client - by Alien - 11 Jun 14, 07:34PM
RE: [Download] 1.2 Mapping Client - by Felix-The-Ghost - 13 Aug 14, 11:28PM
RE: [Download] 1.2 Mapping Client - by PhaNtom - 22 Aug 14, 01:39PM