maxfps 60
fov 120
sensitivity 4.2
-
+w
hudmaxhealthx 0.257
hudmaxhealthy 1.000
CXXFLAGS= -O3 -fomit-frame-pointer -ffast-math
-override CXXFLAGS+= -Wall -Wextra -fsigned-char -fno-exceptions -fno-rtti -Wno-unused-parameter
+override CXXFLAGS+= -Wall -Wextra -fsigned-char -fno-exceptions -fno-rtti
PLATFORM= $(shell uname -s | tr '[:lower:]' '[:upper:]')
PLATFORM_PREFIX= native
void setframes(const animinfo &info)
{
anim = info.anim;
- if(info.range<=1)
+ if(info.range<=1)
{
fr1 = 0;
t = 0;
}
else
{
- float bias = max(mincolor-1.0f, 0.2f), scale = 0.5f*max(0.8f-bias, 0.0f),
+ float bias = max(mincolor-1.0f, 0.2f), scale = 0.5f*max(0.8f-bias, 0.0f),
minshade = scale*max(ambient, mincolor);
LOCALPARAMF(lightscale, scale - minshade, scale, minshade + bias);
}
if(shader) return shader;
string opts;
- int optslen = 0;
+ int optslen = 0;
if(alphatested()) opts[optslen++] = 'a';
if(owner->tangents()) opts[optslen++] = 'q';
if(bumpmapped()) opts[optslen++] = 'n';
{
if(tex->type&Texture::ALPHA && !tex->alphamask) loadalphamask(tex);
}
-
+
void preloadshader(bool force)
{
if(force) cleanup();
loadshader();
}
-
+
void setshader(mesh *m, const animstate *as)
{
m->setshader(loadshader());
}
}
- virtual void setshader(Shader *s)
- {
+ virtual void setshader(Shader *s)
+ {
if(glaring) s->setvariant(0, 1);
- else s->set();
+ else s->set();
}
template<class V, class T> void smoothnorms(V *verts, int numverts, T *tris, int numtris, float limit, bool areaweight)
{
hashtable<vec, int> share;
int *next = new int[numverts];
- memset(next, -1, numverts*sizeof(int));
+ for(int i=0;i<numverts;++i)next[i]=-1;
+ //~memset(next, -1, numverts*sizeof(int));
loopi(numverts)
{
V &v = verts[i];
v3.norm.add(norm);
}
vec *norms = new vec[numverts];
- memclear(norms, numverts);
+ for(int i=0;i<numverts;++i)norms[i]=vec(0,0,0);
+ //~memclear(norms, numverts);
loopi(numverts)
{
V &v = verts[i];
}
loopi(numverts) verts[i].norm.normalize();
}
-
+
template<class V, class T> void buildnorms(V *verts, int numverts, T *tris, int numtris, bool areaweight, int numframes)
{
if(!numverts) return;
loopi(numframes) buildnorms(&verts[i*numverts], numverts, tris, numtris, areaweight);
}
-
+
static inline void fixqtangent(quat &q, float bt)
{
static const float bias = -1.5f/65535, biasscale = sqrtf(1 - bias*bias);
fixqtangent(q, bt);
v.tangent = q;
}
-
+
template<class B, class V, class TC, class T> void calctangents(B *bumpverts, V *verts, TC *tcverts, int numverts, T *tris, int numtris, bool areaweight)
{
vec *tangent = new vec[2*numverts], *bitangent = tangent+numverts;
- memclear(tangent, 2*numverts);
+ for(int i=0;i<2*numverts;++i)tangent[i]=vec(0,0,0);
+ //~memclear(tangent, 2*numverts);
loopi(numtris)
{
const T &t = tris[i];
DELETEA(name);
meshes.deletecontents();
DELETEP(next);
- }
+ }
virtual int findtag(const char *name) { return -1; }
virtual void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) {}
info.frame = 0;
info.range = meshes->totalframes();
}
- else
+ else
{
animspec *spec = NULL;
if(anims[animpart])
{
int secondaryidx = (anim>>ANIM_SECONDARY)&ANIM_INDEX;
if(secondaryidx < NUMANIMS)
- {
+ {
vector<animspec> &secondary = anims[animpart][secondaryidx];
if(secondary.length())
{
animinterpinfo &ai = d->animinterp[interp];
if((info.anim&ANIM_CLAMP)==ANIM_CLAMP) aitime = min(aitime, int(info.range*info.speed*0.5e-3f));
void *ak = meshes->animkey();
- if(d->ragdoll && !(anim&ANIM_RAGDOLL))
+ if(d->ragdoll && !(anim&ANIM_RAGDOLL))
{
ai.prev.range = ai.cur.range = 0;
ai.lastswitch = -1;
meshes->render(as, pitch, oaxis, oforward, d, this);
- if(!(anim&ANIM_REUSE))
+ if(!(anim&ANIM_REUSE))
{
loopv(links)
{
part *p = m->parts[0];
switch(linktype(m))
{
- case LINK_TAG:
+ case LINK_TAG:
if(p->index >= 0) unlink(p);
p->index = 0;
break;
break;
case LINK_REUSE:
- p->render(anim | ANIM_REUSE, basetime, basetime2, pitch, axis, forward, d, as);
+ p->render(anim | ANIM_REUSE, basetime, basetime2, pitch, axis, forward, d, as);
break;
}
}
if(transparent<1)
{
- if(anim&ANIM_GHOST)
+ if(anim&ANIM_GHOST)
{
glDepthFunc(GL_GREATER);
glDepthMask(GL_FALSE);
render(anim, basetime, basetime2, pitch, axis, forward, d, a);
- if(transparent<1 && (alphadepth || anim&ANIM_GHOST))
+ if(transparent<1 && (alphadepth || anim&ANIM_GHOST))
{
glDepthFunc(GL_LESS);
if(anim&ANIM_GHOST) glDepthMask(GL_TRUE);
void setglow(float glow, float delta, float pulse)
{
if(parts.empty()) loaddefaultparts();
- loopv(parts) loopvj(parts[i]->skins)
+ loopv(parts) loopvj(parts[i]->skins)
{
skin &s = parts[i]->skins[j];
s.glow = glow;
if(parts.empty()) return;
vec bbmin(1e16f, 1e16f, 1e16f), bbmax(-1e16f, -1e16f, -1e16f);
matrix4x3 m;
- initmatrix(m);
+ initmatrix(m);
parts[0]->calcbb(bbmin, bbmax, m);
radius = bbmax;
radius.sub(bbmin);
}
#define loopskins(meshname, s, body) loopmeshes(meshname, m, { skin &s = mdl.skins[i]; body; })
-
+
static void setskin(char *meshname, char *tex, char *masks, float *envmapmax, float *envmapmin)
{
loopskins(meshname, s,
}
);
}
-
+
static void setspec(char *meshname, int *percent)
{
float spec = 1.0f;
else if(*percent<0) spec = 0.0f;
loopskins(meshname, s, s.spec = spec);
}
-
+
static void setambient(char *meshname, int *percent)
{
float ambient = 0.3f;
else if(*percent<0) ambient = 0.0f;
loopskins(meshname, s, s.ambient = ambient);
}
-
+
static void setglow(char *meshname, int *percent, int *delta, float *pulse)
{
float glow = 3.0f, glowdelta = *delta/100.0f, glowpulse = *pulse > 0 ? *pulse/1000.0f : 0;
glowdelta -= glow;
loopskins(meshname, s, { s.glow = glow; s.glowdelta = glowdelta; s.glowpulse = glowpulse; });
}
-
+
static void setglare(char *meshname, float *specglare, float *glowglare)
{
loopskins(meshname, s, { s.specglare = *specglare; s.glowglare = *glowglare; });
}
-
+
static void setalphatest(char *meshname, float *cutoff)
{
loopskins(meshname, s, s.alphatest = max(0.0f, min(1.0f, *cutoff)));
}
-
+
static void setalphablend(char *meshname, int *blend)
{
loopskins(meshname, s, s.alphablend = *blend!=0);
}
-
+
static void setcullface(char *meshname, int *cullface)
{
loopskins(meshname, s, s.cullface = *cullface!=0);
}
-
+
static void setenvmap(char *meshname, char *envmap)
{
Texture *tex = cubemapload(envmap);
loopskins(meshname, s, s.envmap = tex);
}
-
+
static void setbumpmap(char *meshname, char *normalmapfile)
{
Texture *normalmaptex = textureload(makerelpath(MDL::dir, normalmapfile), 0, true, false);
loopskins(meshname, s, s.normalmap = normalmaptex);
}
-
+
static void setfullbright(char *meshname, float *fullbright)
{
loopskins(meshname, s, s.fullbright = *fullbright);
}
-
+
static void setshader(char *meshname, char *shader)
{
loopskins(meshname, s, s.shader = lookupshaderbyname(shader));
}
-
+
static void setscroll(char *meshname, float *scrollu, float *scrollv)
{
loopskins(meshname, s, { s.scrollu = *scrollu; s.scrollv = *scrollv; });
}
-
+
static void setnoclip(char *meshname, int *noclip)
{
loopmeshes(meshname, m, m.noclip = *noclip!=0);
}
-
+
static void setlink(int *parent, int *child, char *tagname, float *x, float *y, float *z)
{
if(!MDL::loading) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; }
if(!MDL::loading->parts.inrange(*parent) || !MDL::loading->parts.inrange(*child)) { conoutf(CON_ERROR, "no models loaded to link"); return; }
if(!MDL::loading->parts[*parent]->link(MDL::loading->parts[*child], tagname, vec(*x, *y, *z))) conoutf(CON_ERROR, "could not link model %s", MDL::loading->name);
}
-
+
template<class F> void modelcommand(F *fun, const char *suffix, const char *args)
{
defformatstring(name, "%s%s", MDL::formatname(), suffix);
bool traverse(const vec &o, const vec &ray, float maxdist, float &dist, int mode);
bool traverse(const mesh &m, const vec &o, const vec &ray, const vec &invray, float maxdist, float &dist, int mode, node *curnode, float tmin, float tmax);
bool triintersect(const mesh &m, int tidx, const vec &mo, const vec &mray, float maxdist, float &dist, int mode);
-
+
void preload();
};
extern bool mmintersect(const extentity &e, const vec &o, const vec &ray, float maxdist, int mode, float &dist);
-
VARP(blurdepthfx, 0, 1, 7);
VARP(blurdepthfxsigma, 1, 50, 200);
VAR(depthfxscissor, 0, 2, 2);
-VAR(debugdepthfx, 0, 0, 1);
#define MAXDFXRANGES 4
{
extern void finddepthfxranges();
finddepthfxranges();
- return (numdepthfxranges && scissorx1 < scissorx2 && scissory1 < scissory2) || debugdepthfx;
+ return (numdepthfxranges && scissorx1 < scissorx2 && scissory1 < scissory2);
}
bool dorender()
return numdepthfxranges > 0;
}
-
- void dodebug(int w, int h)
- {
- if(numdepthfxranges > 0)
- {
- gle::colorf(0, 1, 0);
- debugscissor(w, h, true);
- gle::colorf(0, 0, 1);
- debugblurtiles(w, h, true);
- gle::colorf(1, 1, 1);
- }
- }
} depthfxtex;
void cleanupdepthfx()
depthfxtex.cleanup(true);
}
-void viewdepthfxtex()
-{
- if(!depthfx) return;
- depthfxtex.debug();
-}
-
bool depthfxing = false;
bool binddepthfxtex()
{
- if(!reflecting && !refracting && depthfx && depthfxtex.rendertex && numdepthfxranges>0)
+ if(!reflecting && !refracting && depthfx && depthfxtex.rendertex && numdepthfxranges>0)
{
glActiveTexture_(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, depthfxtex.rendertex);
extern void updatesounds();
extern void preloadmapsounds();
-extern void initmumble();
-extern void closemumble();
-extern void updatemumble();
-
// blendmap
extern int blendpaintmode;
#endif
#endif
-
VARP(blurglareaspect, 0, 1, 1);
VARP(blurglaresigma, 1, 50, 200);
-VAR(debugglare, 0, 0, 1);
-
-void viewglaretex()
-{
- if(!glare) return;
- glaretex.debug();
-}
-
bool glaring = false;
void drawglaretex()
bool insert(ushort &tx, ushort &ty, ushort tw, ushort th);
};
-enum
-{
- LM_DIFFUSE = 0,
- LM_BUMPMAP0,
- LM_BUMPMAP1,
+enum
+{
+ LM_DIFFUSE = 0,
+ LM_BUMPMAP0,
+ LM_BUMPMAP1,
LM_TYPE = 0x0F,
- LM_ALPHA = 1<<4,
- LM_FLAGS = 0xF0
+ LM_ALPHA = 1<<4,
+ LM_FLAGS = 0xF0
};
struct LightMap
int type, bpp, tex, offsetx, offsety;
PackNode packroot;
uint lightmaps, lumels;
- int unlitx, unlity;
+ int unlitx, unlity;
uchar *data;
LightMap()
bool operator==(const lerpvert &l) const { return tc == l.tc;; }
bool operator!=(const lerpvert &l) const { return tc != l.tc; }
};
-
+
struct lerpbounds
{
const lerpvert *min;
gettextres(w, h);
static int lastupdate = -1, lastw = -1, lasth = -1;
- //~static float backgroundu = 0, backgroundv = 0, detailu = 0, detailv = 0;
static int numdecals = 0;
static struct decal { float x, y, size; int side; } decals[12];
if((renderedframe && !mainmenu && lastupdate != lastmillis) || lastw != w || lasth != h)
lastw = w;
lasth = h;
- //~backgroundu = rndscale(1);
- //~backgroundv = rndscale(1);
- //~detailu = rndscale(1);
- //~detailv = rndscale(1);
numdecals = sizeof(decals)/sizeof(decals[0]);
numdecals = numdecals/3 + rnd((numdecals*2)/3 + 1);
float maxsize = min(w, h)/16.0f;
}
else if(lastupdate != lastmillis) lastupdate = lastmillis;
- //~if (mapname) {
- //~defformatstring(backpath, "background/%s.png", mapname);
- //~if (file_does_indeed_exist(backpath)) {
- //~settexture(backpath, 0);
- //~bgquad(0, 0, 1920, 1080, 0, 0, 1920, 1080);
- //~gle::begin(GL_TRIANGLE_STRIP);
- //~gle::attribf(0.0f, 0.0f); gle::attribf(0.0f, 0.0f);
- //~gle::attribf(1.0f, 0.0f); gle::attribf(1920.0f, 0.0f);
- //~gle::attribf(0.0f, 1.0f); gle::attribf(0.0f, 1.0f);
- //~gle::attribf(1.0f, 1.0f); gle::attribf(1920.0f, 1.0f);
- //~gle::end();
- //~}
- //~} else {
loopi(restore ? 1 : 3)
{
hudmatrix.ortho(0, w, h, 0, -1, 1);
gle::defvertex(2);
gle::deftexcoord0();
- //~defformatstring(backpath, "background/%s.png", mapname);
- //~if (file_does_indeed_exist(backpath)) {
- //~settexture(backpath, 0);
settexture("background/daemex.png", 0);
bgquad(0, 0, screenw, screenh, 0, 0, 1, 1);
- //~settexture("data/background.png", 0);
- //~float bu = w*0.67f/256.0f + backgroundu, bv = h*0.67f/256.0f + backgroundv;
- //~bgquad(0, 0, w, h, 0, 0, bu, bv);
- //~glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- //~settexture("data/background_detail.png", 0);
- //~float du = w*0.8f/512.0f + detailu, dv = h*0.8f/512.0f + detailv;
- //~bgquad(0, 0, w, h, 0, 0, du, dv);
- //~settexture("data/background_decal.png", 3);
- //~gle::begin(GL_QUADS);
- //~loopj(numdecals)
- //~{
- //~float hsz = decals[j].size, hx = clamp(decals[j].x, hsz, w-hsz), hy = clamp(decals[j].y, hsz, h-hsz), side = decals[j].side;
- //~gle::attribf(hx-hsz, hy-hsz); gle::attribf(side, 0);
- //~gle::attribf(hx+hsz, hy-hsz); gle::attribf(1-side, 0);
- //~gle::attribf(hx+hsz, hy+hsz); gle::attribf(1-side, 1);
- //~gle::attribf(hx-hsz, hy+hsz); gle::attribf(side, 1);
- //~}
- //~gle::end();
float lh = 0.5f*min(w, h), lw = lh*2,
lx = 0.5f*(w - lw), ly = 0.5f*(h*0.5f - lh);
settexture((maxtexsize ? min(maxtexsize, hwtexsize) : hwtexsize) >= 1024 && (screenw > 1280 || screenh > 800) ? "data/logo_1024.png" : "data/logo.png", 3);
glDisable(GL_BLEND);
if(!restore) swapbuffers(false);
}
- //~}
if(!restore) setbackgroundinfo(caption, mapshot, mapname, mapinfo);
}
if(initscript) execute(initscript);
- initmumble();
resetfpshistory();
inputgrab(grabinput = true);
-#ifdef WIN32
-#define FD_SETSIZE 4096
-#else
#include <sys/types.h>
#undef __FD_SETSIZE
#define __FD_SETSIZE 4096
-#endif
#include "cube.h"
#include <signal.h>
loopv(gbans)
{
ipmask &b = gbans[i];
- l->buf.put(cmd, cmdlen + b.print(&cmd[cmdlen]));
+ l->buf.put(cmd, cmdlen + b.print(&cmd[cmdlen]));
l->buf.add('\n');
}
if(gbanlists.length() && gbanlists.last()->equals(*l))
loopv(clients)
{
client &c = *clients[i];
- if(c.servport >= 0 && !c.message)
+ if(c.servport >= 0 && !c.message)
{
c.message = l;
c.message->refs++;
{
if(c.output.length()) c.output.setsize(0);
else
- {
+ {
c.message->purge();
- c.message = NULL;
+ c.message = NULL;
}
c.outputpos = 0;
if(!c.message && c.output.empty() && c.shouldpurge)
volatile int reloadcfg = 1;
-#ifndef WIN32
void reloadsignal(int signum)
{
reloadcfg = 1;
}
-#endif
int main(int argc, char **argv)
{
logfile = fopen(logname, "a");
if(!logfile) logfile = stdout;
setvbuf(logfile, NULL, _IOLBF, BUFSIZ);
-#ifndef WIN32
signal(SIGUSR1, reloadsignal);
-#endif
setupserver(port, ip);
for(;;)
{
#include "engine.h"
-struct QuadNode
-{
+struct QuadNode {
int x, y, size;
uint filled;
QuadNode *child[4];
QuadNode(int x, int y, int size) : x(x), y(y), size(size), filled(0) { loopi(4) child[i] = 0; }
- void clear()
- {
- loopi(4) DELETEP(child[i]);
- }
-
- ~QuadNode()
- {
- clear();
- }
+ void clear() { loopi(4) DELETEP(child[i]); }
- void insert(int mx, int my, int msize)
- {
- if(size == msize)
- {
+ ~QuadNode() { clear(); }
+
+ void insert(int mx, int my, int msize) {
+ if(size == msize) {
filled = 0xF;
return;
}
int csize = size>>1, i = 0;
if(mx >= x+csize) i |= 1;
if(my >= y+csize) i |= 2;
- if(csize == msize)
- {
+ if(csize == msize) {
filled |= (1 << i);
return;
}
child[i]->insert(mx, my, msize);
loopj(4) if(child[j])
{
- if(child[j]->filled == 0xF)
- {
+ if(child[j]->filled == 0xF) {
DELETEP(child[j]);
filled |= (1 << j);
}
}
}
- void genmatsurf(ushort mat, uchar orient, uchar visible, int x, int y, int z, int size, materialsurface *&matbuf)
- {
+ void genmatsurf(ushort mat, uchar orient, uchar visible, int x, int y, int z, int size, materialsurface *&matbuf) {
materialsurface &m = *matbuf++;
m.material = mat;
m.orient = orient;
m.o[dim] = z;
}
- void genmatsurfs(ushort mat, uchar orient, uchar flags, int z, materialsurface *&matbuf)
- {
+ void genmatsurfs(ushort mat, uchar orient, uchar flags, int z, materialsurface *&matbuf) {
if(filled == 0xF) genmatsurf(mat, orient, flags, x, y, z, size, matbuf);
else if(filled)
{
static float wfwave;
-static const bvec4 matnormals[6] =
-{
+static const bvec4 matnormals[6] = {
bvec4(0x80, 0, 0),
bvec4(0x7F, 0, 0),
bvec4(0, 0x80, 0),
{
const char *name;
ushort id;
-} materials[] =
+} materials[] =
{
{"air", MAT_AIR},
{"water", MAT_WATER}, {"water1", MAT_WATER}, {"water2", MAT_WATER+1}, {"water3", MAT_WATER+2}, {"water4", MAT_WATER+3},
loopi(sizeof(materials)/sizeof(material))
{
if(!strcmp(materials[i].name, name)) return materials[i].id;
- }
+ }
return -1;
-}
+}
const char *findmaterialname(int mat)
{
loopi(sizeof(materials)/sizeof(materials[0])) if(materials[i].id == mat) return materials[i].name;
return NULL;
}
-
+
const char *getmaterialdesc(int mat, const char *prefix)
{
static const ushort matmasks[] = { MATF_VOLUME|MATF_INDEX, MATF_CLIP, MAT_DEATH, MAT_ALPHA };
loopi(sizeof(matmasks)/sizeof(matmasks[0])) if(mat&matmasks[i])
{
const char *matname = findmaterialname(mat&matmasks[i]);
- if(matname)
+ if(matname)
{
concatstring(desc, desc[0] ? ", " : prefix);
concatstring(desc, matname);
}
return desc;
}
-
+
int visiblematerial(const cube &c, int orient, const ivec &co, int size, ushort matmask)
-{
+{
ushort mat = c.material&matmask;
switch(mat)
{
{
int matmask = matmasks[j];
int vis = visiblematerial(c, i, co, size, matmask&~MATF_INDEX);
- if(vis != MATSURF_NOT_VISIBLE)
+ if(vis != MATSURF_NOT_VISIBLE)
{
materialsurface m;
m.material = c.material&matmask;
while(cur < end &&
cur->material == start->material &&
cur->orient == start->orient &&
- cur->visible == start->visible &&
+ cur->visible == start->visible &&
cur->o[dim] == start->o[dim])
++cur;
if(!isliquid(start->material&MATF_VOLUME) || start->orient != O_TOP || !vertwater)
vector<waterinfo> water;
unionfind uf;
if(!len) len = valist.length();
- for(int i = start; i < len; i++)
+ for(int i = start; i < len; i++)
{
vtxarray *va = valist[i];
materialsurface *skip = NULL;
m.light = brightestlight(center, vec(0, 0, 1));
float depth = raycube(center, vec(0, 0, -1), 10000);
wi.depth = double(depth)*m.rsize*m.csize;
- wi.area = m.rsize*m.csize;
+ wi.area = m.rsize*m.csize;
}
else if(isliquid(matvol) && m.orient!=O_BOTTOM && m.orient!=O_TOP)
{
m.skip = 0;
if(skip && m.material == skip->material && m.orient == skip->orient && skip->skip < 0xFFFF)
skip->skip++;
- else
+ else
skip = &m;
}
}
preloadwatershaders(true);
loopi(4) if(hasmat&(1<<(MAT_WATER+i))) lookupmaterialslot(MAT_WATER+i);
}
- if(hasmat&(0xF<<MAT_LAVA))
+ if(hasmat&(0xF<<MAT_LAVA))
{
useshaderbyname("lava");
useshaderbyname("lavaglare");
if(waterfallrefract && wfog && !reflecting && !refracting)
{
- if(waterfallenv) SETSHADER(waterfallenvrefract);
+ if(waterfallenv) SETSHADER(waterfallenvrefract);
else SETSHADER(waterfallrefract);
if(blended) { glDisable(GL_BLEND); blended = false; }
if(!depth) { glDepthMask(GL_TRUE); depth = true; }
}
- else
+ else
{
SETSHADER(waterfallenv);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
usedwaterfall = m.material;
}
}
- float angle = fmod(float(lastmillis/600.0f/(2*M_PI)), 1.0f),
+ float angle = fmod(float(lastmillis/600.0f/(2*M_PI)), 1.0f),
s = angle - int(angle) - 0.5f;
s *= 8 - fabs(s)*16;
wfwave = vertwater ? WATER_AMPLITUDE*s-WATER_OFFSET : -WATER_OFFSET;
{
if(!blended) { glEnable(GL_BLEND); blended = true; }
if(depth) { glDepthMask(GL_FALSE); depth = false; }
- const bvec &gcol = getglasscolor(m.material);
+ const bvec &gcol = getglasscolor(m.material);
if(m.envmap!=EMID_NONE && glassenv)
{
glBlendFunc(GL_ONE, GL_SRC_ALPHA);
}
}
break;
-
+
default: continue;
}
lastmat = m.material;
VAR(glslversion, 1, 0, 0);
VAR(glcompat, 1, 0, 0);
-// OpenGL 1.3
-#ifdef WIN32
-PFNGLACTIVETEXTUREPROC glActiveTexture_ = NULL;
-
-PFNGLBLENDEQUATIONEXTPROC glBlendEquation_ = NULL;
-PFNGLBLENDCOLOREXTPROC glBlendColor_ = NULL;
-
-PFNGLTEXIMAGE3DPROC glTexImage3D_ = NULL;
-PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D_ = NULL;
-PFNGLCOPYTEXSUBIMAGE3DPROC glCopyTexSubImage3D_ = NULL;
-
-PFNGLCOMPRESSEDTEXIMAGE3DPROC glCompressedTexImage3D_ = NULL;
-PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D_ = NULL;
-PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glCompressedTexSubImage3D_ = NULL;
-PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glCompressedTexSubImage2D_ = NULL;
-PFNGLGETCOMPRESSEDTEXIMAGEPROC glGetCompressedTexImage_ = NULL;
-
-PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements_ = NULL;
-#endif
-
// OpenGL 2.0
-#ifndef __APPLE__
PFNGLMULTIDRAWARRAYSPROC glMultiDrawArrays_ = NULL;
PFNGLMULTIDRAWELEMENTSPROC glMultiDrawElements_ = NULL;
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer_ = NULL;
PFNGLDRAWBUFFERSPROC glDrawBuffers_ = NULL;
-#endif
// OpenGL 3.0
PFNGLGETSTRINGIPROC glGetStringi_ = NULL;
if(glversion < 200) fatal("OpenGL 2.0 or greater is required!");
-#ifdef WIN32
- glActiveTexture_ = (PFNGLACTIVETEXTUREPROC) getprocaddress("glActiveTexture");
-
- glBlendEquation_ = (PFNGLBLENDEQUATIONPROC) getprocaddress("glBlendEquation");
- glBlendColor_ = (PFNGLBLENDCOLORPROC) getprocaddress("glBlendColor");
-
- glTexImage3D_ = (PFNGLTEXIMAGE3DPROC) getprocaddress("glTexImage3D");
- glTexSubImage3D_ = (PFNGLTEXSUBIMAGE3DPROC) getprocaddress("glTexSubImage3D");
- glCopyTexSubImage3D_ = (PFNGLCOPYTEXSUBIMAGE3DPROC) getprocaddress("glCopyTexSubImage3D");
-
- glCompressedTexImage3D_ = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) getprocaddress("glCompressedTexImage3D");
- glCompressedTexImage2D_ = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) getprocaddress("glCompressedTexImage2D");
- glCompressedTexSubImage3D_ = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) getprocaddress("glCompressedTexSubImage3D");
- glCompressedTexSubImage2D_ = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) getprocaddress("glCompressedTexSubImage2D");
- glGetCompressedTexImage_ = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) getprocaddress("glGetCompressedTexImage");
-
- glDrawRangeElements_ = (PFNGLDRAWRANGEELEMENTSPROC) getprocaddress("glDrawRangeElements");
-#endif
-
-#ifndef __APPLE__
glMultiDrawArrays_ = (PFNGLMULTIDRAWARRAYSPROC) getprocaddress("glMultiDrawArrays");
glMultiDrawElements_ = (PFNGLMULTIDRAWELEMENTSPROC) getprocaddress("glMultiDrawElements");
glVertexAttribPointer_ = (PFNGLVERTEXATTRIBPOINTERPROC) getprocaddress("glVertexAttribPointer");
glDrawBuffers_ = (PFNGLDRAWBUFFERSPROC) getprocaddress("glDrawBuffers");
-#endif
if(glversion >= 300)
{
}
else
{
- if(intel)
- {
-#ifdef WIN32
- intel_vertexarray_bug = 1;
- // MapBufferRange is buggy on older Intel drivers on Windows
- if(glversion <= 310) intel_mapbufferrange_bug = 1;
-#endif
- }
-
reservevpparams = 20;
if(mesa) mesa_swap_bug = 1;
gle::colorf(1, 1, 1);
- extern int debugsm;
- if(debugsm)
- {
- extern void viewshadowmap();
- viewshadowmap();
- }
-
- extern int debugglare;
- if(debugglare)
- {
- extern void viewglaretex();
- viewglaretex();
- }
-
- extern int debugdepthfx;
- if(debugdepthfx)
- {
- extern void viewdepthfxtex();
- viewdepthfxtex();
- }
-
glEnable(GL_BLEND);
- extern void debugparticles();
- debugparticles();
-
if(!mainmenu)
{
drawdamagescreen(w, h);
if(!m) return;
vec center(0, 0, 0), bbradius(0, 0, 0);
float radius = 0;
- bool shadow = !shadowmap && !glaring && (flags&(MDL_SHADOW|MDL_DYNSHADOW));//~ && showblobs;
+ bool shadow = !shadowmap && !glaring && (flags&(MDL_SHADOW|MDL_DYNSHADOW));
if(flags&(MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED|MDL_CULL_QUERY|MDL_SHADOW|MDL_DYNSHADOW))
{
virtual void update() { }
virtual void render() = 0;
virtual bool haswork() = 0;
- virtual int count() = 0; //for debug
virtual void cleanup() {}
virtual void seedemitter(particleemitter &pe, const vec &o, const vec &d, int fade, float size, int gravity)
}
}
}
-
- const char *debuginfo()
- {
- formatstring(info, "%d\t%s(", count(), partnames[type&0xFF]);
- if(type&PT_GLARE) concatstring(info, "g,");
- if(type&PT_SOFT) concatstring(info, "s,");
- if(type&PT_LERP) concatstring(info, "l,");
- if(type&PT_MOD) concatstring(info, "m,");
- if(type&PT_RND4) concatstring(info, "r,");
- if(type&PT_FLIP) concatstring(info, "f,");
- if(collide) concatstring(info, "c,");
- int len = strlen(info);
- info[len-1] = info[len-1] == ',' ? ')' : '\0';
- if(texname)
- {
- const char *title = strrchr(texname, '/');
- if(title) concformatstring(info, ": %s", title+1);
- }
- return info;
- }
};
struct listparticle : particle
VARP(particleglare, 0, 2, 100);
-VARN(debugparticles, dbgparts, 0, 0, 1);
-
-void debugparticles()
-{
- if(!dbgparts) return;
- int n = sizeof(parts)/sizeof(parts[0]);
- pushhudmatrix();
- hudmatrix.ortho(0, FONTH*n*2*screenw/float(screenh), FONTH*n*2, 0, -1, 1); //squeeze into top-left corner
- flushhudmatrix();
- hudshader->set();
- loopi(n) draw_text(parts[i]->info, FONTH, (i+n/2)*FONTH);
- pophudmatrix();
-}
-
void renderparticles(bool mainpass)
{
canstep = mainpass;
- //want to debug BEFORE the lastpass render (that would delete particles)
- if(dbgparts && mainpass) loopi(sizeof(parts)/sizeof(parts[0])) parts[i]->debuginfo();
if(glaring && !particleglare) return;
while(!depthfmt && depthfmts[++find]);
if(!depthfmt) depthfmt = depthfmts[find];
}
-
+
glBindFramebuffer_(GL_FRAMEBUFFER, 0);
texw = w;
bool checkblurtiles(float x1, float y1, float x2, float y2, float blurmargin = 0)
{
float blurerror = 2.0f*float(2*blursize + blurmargin);
- if(x2+blurerror/vieww < scissorx1 || y2+blurerror/viewh < scissory1 ||
- x1-blurerror/vieww > scissorx2 || y1-blurerror/viewh > scissory2)
+ if(x2+blurerror/vieww < scissorx1 || y2+blurerror/viewh < scissory1 ||
+ x1-blurerror/vieww > scissorx2 || y1-blurerror/viewh > scissory2)
return false;
if(!blurtile) return true;
}
if(scissor) glDisable(GL_SCISSOR_TEST);
-
+
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
}
virtual bool shouldrender() { return true; }
virtual void doblur(int blursize, float blursigma, int blurysize)
- {
+ {
int sx, sy, sw, sh;
bool scissoring = rtscissor && scissorblur(sx, sy, sw, sh) && sw > 0 && sh > 0;
if(!scissoring) { sx = sy = 0; sw = vieww; sh = viewh; }
virtual bool scissorrender(int &x, int &y, int &w, int &h)
{
- if(scissorx1 >= scissorx2 || scissory1 >= scissory2)
+ if(scissorx1 >= scissorx2 || scissory1 >= scissory2)
{
if(vieww < texw || viewh < texh)
{
vieww = w;
viewh = h;
if(w!=texw || h!=texh || (swaptexs() && !rtsharefb ? !blurfb : blurfb)) cleanup();
-
+
if(!filter())
{
if(blurtex) cleanupblur();
blursize = blurysize = 0;
}
-
+
if(!rendertex) setup(w, h);
-
+
scissorx2 = scissory2 = -1;
scissorx1 = scissory1 = 1;
memset(blurtiles, 0, sizeof(blurtiles));
-
+
if(!shouldrender()) return;
if(blursize && !blurtex) setupblur();
glBindFramebuffer_(GL_FRAMEBUFFER, 0);
glViewport(0, 0, screenw, screenh);
}
-
- virtual void dodebug(int w, int h) {}
- virtual bool flipdebug() const { return true; }
-
- void debugscissor(int w, int h, bool lines = false)
- {
- if(!rtscissor || scissorx1 >= scissorx2 || scissory1 >= scissory2) return;
- int sx = int(0.5f*(scissorx1 + 1)*w),
- sy = int(0.5f*(scissory1 + 1)*h),
- sw = int(0.5f*(scissorx2 - scissorx1)*w),
- sh = int(0.5f*(scissory2 - scissory1)*h);
- if(flipdebug()) { sy = h - sy; sh = -sh; }
- gle::defvertex(2);
- gle::begin(lines ? GL_LINE_LOOP : GL_TRIANGLE_STRIP);
- gle::attribf(sx, sy);
- gle::attribf(sx + sw, sy);
- if(lines) gle::attribf(sx + sw, sy + sh);
- gle::attribf(sx, sy + sh);
- if(!lines) gle::attribf(sx + sw, sy + sh);
- gle::end();
- }
-
- void debugblurtiles(int w, int h, bool lines = false)
- {
- if(!blurtile) return;
- float vxsz = float(w)/BLURTILES, vysz = float(h)/BLURTILES;
- gle::defvertex(2);
- loop(y, BLURTILES+1)
- {
- uint mask = blurtiles[y];
- int x = 0;
- while(mask)
- {
- while(!(mask&0xFF)) { mask >>= 8; x += 8; }
- while(!(mask&1)) { mask >>= 1; x++; }
- int xstart = x;
- do { mask >>= 1; x++; } while(mask&1);
- uint strip = (BLURTILEMASK>>(BLURTILES - x)) & (BLURTILEMASK<<xstart);
- int yend = y;
- do { blurtiles[yend] &= ~strip; yend++; } while((blurtiles[yend] & strip) == strip);
- float vx = xstart*vxsz,
- vy = y*vysz,
- vw = (x-xstart)*vxsz,
- vh = (yend-y)*vysz;
- if(flipdebug()) { vy = h - vy; vh = -vh; }
- loopi(lines ? 1 : 2)
- {
- if(!lines) gle::colorf(1, 1, i ? 1.0f : 0.5f);
- gle::begin(lines || i ? GL_LINE_LOOP : GL_TRIANGLE_STRIP);
- gle::attribf(vx, vy);
- gle::attribf(vx+vw, vy);
- if(lines || i) gle::attribf(vx+vw, vy+vh);
- gle::attribf(vx, vy+vh);
- if(!lines && !i) gle::attribf(vx+vw, vy+vh);
- gle::end();
- }
- }
- }
- }
-
- void debug()
- {
- if(!rendertex) return;
- int w = min(screenw, screenh)/2, h = (w*screenh)/screenw;
- hudshader->set();
- gle::colorf(1, 1, 1);
- glBindTexture(GL_TEXTURE_2D, rendertex);
- float tx1 = 0, tx2 = 1, ty1 = 0, ty2 = 1;
- if(flipdebug()) swap(ty1, ty2);
- hudquad(0, 0, w, h, tx1, ty1, tx2-tx1, ty2-ty1);
- hudnotextureshader->set();
- dodebug(w, h);
- }
};
v.curvfc = isvisiblecube(v.o, v.size);
if(v.curvfc!=VFC_NOT_VISIBLE)
{
- //~if(pvsoccluded(v.o, v.size))
- //~{
- //~v.curvfc += PVS_FULL_VISIBLE - VFC_FULL_VISIBLE;
- //~continue;
- //~}
addvisibleva(&v);
if(v.children.length()) findvisiblevas(v.children, prevvfc>=VFC_NOT_VISIBLE);
if(prevvfc>=VFC_NOT_VISIBLE)
FILE *getlogfile()
{
-#ifdef WIN32
- return logfile;
-#else
return logfile ? logfile : stdout;
-#endif
}
void setlogfile(const char *fname)
vformatstring(buf, fmt, args, sizeof(buf));
writelog(file, buf);
}
-
+
#ifdef STANDALONE
-void fatal(const char *fmt, ...)
-{
+void fatal(const char *fmt, ...)
+{
void cleanupserver();
- cleanupserver();
+ cleanupserver();
defvformatstring(msg,fmt,fmt);
if(logfile) logoutf("%s", msg);
-#ifdef WIN32
- MessageBox(NULL, msg, "Cube 2: Sauerbraten fatal error", MB_OK|MB_SYSTEMMODAL);
-#else
fprintf(stderr, "server error: %s\n", msg);
-#endif
closelogfile();
- exit(EXIT_FAILURE);
+ exit(EXIT_FAILURE);
}
void conoutfv(int type, const char *fmt, va_list args)
vector<client *> clients;
ENetHost *serverhost = NULL;
-int laststatus = 0;
+int laststatus = 0;
ENetSocket pongsock = ENET_SOCKET_NULL, lansock = ENET_SOCKET_NULL;
int localclients = 0, nonlocalclients = 0;
break;
}
- case 'i':
+ case 'i':
{
int n = isdigit(*format) ? *format++-'0' : 1;
loopi(n) putint(p, va_arg(args, int));
void disconnectmaster()
{
- if(mastersock != ENET_SOCKET_NULL)
+ if(mastersock != ENET_SOCKET_NULL)
{
server::masterdisconnected();
enet_socket_destroy(mastersock);
masterinpos = end - masterin.getbuf();
input = end;
end = (char *)memchr(input, '\n', masterin.length() - masterinpos);
- }
+ }
if(masterinpos >= masterin.length())
{
{
if(!masterconnected)
{
- if(ENET_SOCKETSET_CHECK(readset, mastersock) || ENET_SOCKETSET_CHECK(writeset, mastersock))
- {
+ if(ENET_SOCKETSET_CHECK(readset, mastersock) || ENET_SOCKETSET_CHECK(writeset, mastersock))
+ {
int error = 0;
if(enet_socket_get_option(mastersock, ENET_SOCKOPT_ERROR, &error) < 0 || error)
{
}
else
{
- masterconnecting = 0;
- masterconnected = totalmillis ? totalmillis : 1;
- server::masterconnected();
+ masterconnecting = 0;
+ masterconnected = totalmillis ? totalmillis : 1;
+ server::masterconnected();
}
}
}
void updatetime()
{
static int lastsec = 0;
- if(totalmillis - lastsec >= 1000)
+ if(totalmillis - lastsec >= 1000)
{
int cursecs = (totalmillis - lastsec) / 1000;
totalsecs += cursecs;
void serverslice(bool dedicated, uint timeout) // main server update, called from main loop in sp, or from below in dedicated server
{
- if(!serverhost)
+ if(!serverhost)
{
server::serverupdate();
server::sendpackets();
return;
}
-
+
// below is network only
- if(dedicated)
+ if(dedicated)
{
int millis = (int)enet_time_get();
elapsedtime = millis - totalmillis;
if(!lastupdatemaster || totalmillis-lastupdatemaster>60*60*1000) // send alive signal to masterserver every hour of uptime
updatemasterserver();
-
+
if(totalmillis-laststatus>60*1000) // display bandwidth stats, useful for server ops
{
- laststatus = totalmillis;
+ laststatus = totalmillis;
if(nonlocalclients || serverhost->totalSentData || serverhost->totalReceivedData) logoutf("status: %d remote clients, %.1f send, %.1f rec (K/sec)", nonlocalclients, serverhost->totalSentData/60.0f/1024, serverhost->totalReceivedData/60.0f/1024);
serverhost->totalSentData = serverhost->totalReceivedData = 0;
}
string hn;
copystring(c.hostname, (enet_address_get_host_ip(&c.peer->address, hn, sizeof(hn))==0) ? hn : "unknown");
logoutf("client connected (%s)", c.hostname);
- int reason = server::clientconnect(c.num, c.peer->address.host);
+ int reason = server::clientconnect(c.num);
if(reason) disconnect_client(c.num, reason);
break;
}
if(event.packet->referenceCount==0) enet_packet_destroy(event.packet);
break;
}
- case ENET_EVENT_TYPE_DISCONNECT:
+ case ENET_EVENT_TYPE_DISCONNECT:
{
client *c = (client *)event.peer->data;
if(!c) break;
void localdisconnect(bool cleanup)
{
bool disconnected = false;
- loopv(clients) if(clients[i]->type==ST_LOCAL)
+ loopv(clients) if(clients[i]->type==ST_LOCAL)
{
server::localdisconnect(i);
delclient(clients[i]);
}
#endif
-#ifdef WIN32
-#include "shellapi.h"
-
-#define IDI_ICON1 1
-
-static string apptip = "";
-static HINSTANCE appinstance = NULL;
-static ATOM wndclass = 0;
-static HWND appwindow = NULL, conwindow = NULL;
-static HICON appicon = NULL;
-static HMENU appmenu = NULL;
-static HANDLE outhandle = NULL;
-static const int MAXLOGLINES = 200;
-struct logline { int len; char buf[LOGSTRLEN]; };
-static queue<logline, MAXLOGLINES> loglines;
-
-static void cleanupsystemtray()
-{
- NOTIFYICONDATA nid;
- memset(&nid, 0, sizeof(nid));
- nid.cbSize = sizeof(nid);
- nid.hWnd = appwindow;
- nid.uID = IDI_ICON1;
- Shell_NotifyIcon(NIM_DELETE, &nid);
-}
-
-static bool setupsystemtray(UINT uCallbackMessage)
-{
- NOTIFYICONDATA nid;
- memset(&nid, 0, sizeof(nid));
- nid.cbSize = sizeof(nid);
- nid.hWnd = appwindow;
- nid.uID = IDI_ICON1;
- nid.uCallbackMessage = uCallbackMessage;
- nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
- nid.hIcon = appicon;
- strcpy(nid.szTip, apptip);
- if(Shell_NotifyIcon(NIM_ADD, &nid) != TRUE)
- return false;
- atexit(cleanupsystemtray);
- return true;
-}
-
-#if 0
-static bool modifysystemtray()
-{
- NOTIFYICONDATA nid;
- memset(&nid, 0, sizeof(nid));
- nid.cbSize = sizeof(nid);
- nid.hWnd = appwindow;
- nid.uID = IDI_ICON1;
- nid.uFlags = NIF_TIP;
- strcpy(nid.szTip, apptip);
- return Shell_NotifyIcon(NIM_MODIFY, &nid) == TRUE;
-}
-#endif
-
-static void cleanupwindow()
-{
- if(!appinstance) return;
- if(appmenu)
- {
- DestroyMenu(appmenu);
- appmenu = NULL;
- }
- if(wndclass)
- {
- UnregisterClass(MAKEINTATOM(wndclass), appinstance);
- wndclass = 0;
- }
-}
-
-static BOOL WINAPI consolehandler(DWORD dwCtrlType)
-{
- switch(dwCtrlType)
- {
- case CTRL_C_EVENT:
- case CTRL_BREAK_EVENT:
- case CTRL_CLOSE_EVENT:
- exit(EXIT_SUCCESS);
- return TRUE;
- }
- return FALSE;
-}
-
-static void writeline(logline &line)
-{
- static uchar ubuf[512];
- size_t len = strlen(line.buf), carry = 0;
- while(carry < len)
- {
- size_t numu = encodeutf8(ubuf, sizeof(ubuf), &((uchar *)line.buf)[carry], len - carry, &carry);
- DWORD written = 0;
- WriteConsole(outhandle, ubuf, numu, &written, NULL);
- }
-}
-
-static void setupconsole()
-{
- if(conwindow) return;
- if(!AllocConsole()) return;
- SetConsoleCtrlHandler(consolehandler, TRUE);
- conwindow = GetConsoleWindow();
- SetConsoleTitle(apptip);
- //SendMessage(conwindow, WM_SETICON, ICON_SMALL, (LPARAM)appicon);
- SendMessage(conwindow, WM_SETICON, ICON_BIG, (LPARAM)appicon);
- outhandle = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_SCREEN_BUFFER_INFO coninfo;
- GetConsoleScreenBufferInfo(outhandle, &coninfo);
- coninfo.dwSize.Y = MAXLOGLINES;
- SetConsoleScreenBufferSize(outhandle, coninfo.dwSize);
- SetConsoleCP(CP_UTF8);
- SetConsoleOutputCP(CP_UTF8);
- loopv(loglines) writeline(loglines[i]);
-}
-
-enum
-{
- MENU_OPENCONSOLE = 0,
- MENU_SHOWCONSOLE,
- MENU_HIDECONSOLE,
- MENU_EXIT
-};
-
-static LRESULT CALLBACK handlemessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-{
- switch(uMsg)
- {
- case WM_APP:
- SetForegroundWindow(hWnd);
- switch(lParam)
- {
- //case WM_MOUSEMOVE:
- // break;
- case WM_LBUTTONUP:
- case WM_RBUTTONUP:
- {
- POINT pos;
- GetCursorPos(&pos);
- TrackPopupMenu(appmenu, TPM_CENTERALIGN|TPM_BOTTOMALIGN|TPM_RIGHTBUTTON, pos.x, pos.y, 0, hWnd, NULL);
- PostMessage(hWnd, WM_NULL, 0, 0);
- break;
- }
- }
- return 0;
- case WM_COMMAND:
- switch(LOWORD(wParam))
- {
- case MENU_OPENCONSOLE:
- setupconsole();
- if(conwindow) ModifyMenu(appmenu, 0, MF_BYPOSITION|MF_STRING, MENU_HIDECONSOLE, "Hide Console");
- break;
- case MENU_SHOWCONSOLE:
- ShowWindow(conwindow, SW_SHOWNORMAL);
- ModifyMenu(appmenu, 0, MF_BYPOSITION|MF_STRING, MENU_HIDECONSOLE, "Hide Console");
- break;
- case MENU_HIDECONSOLE:
- ShowWindow(conwindow, SW_HIDE);
- ModifyMenu(appmenu, 0, MF_BYPOSITION|MF_STRING, MENU_SHOWCONSOLE, "Show Console");
- break;
- case MENU_EXIT:
- PostMessage(hWnd, WM_CLOSE, 0, 0);
- break;
- }
- return 0;
- case WM_CLOSE:
- PostQuitMessage(0);
- return 0;
- }
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
-}
-
-static void setupwindow(const char *title)
-{
- copystring(apptip, title);
- //appinstance = GetModuleHandle(NULL);
- if(!appinstance) fatal("failed getting application instance");
- appicon = LoadIcon(appinstance, MAKEINTRESOURCE(IDI_ICON1));//(HICON)LoadImage(appinstance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
- if(!appicon) fatal("failed loading icon");
-
- appmenu = CreatePopupMenu();
- if(!appmenu) fatal("failed creating popup menu");
- AppendMenu(appmenu, MF_STRING, MENU_OPENCONSOLE, "Open Console");
- AppendMenu(appmenu, MF_SEPARATOR, 0, NULL);
- AppendMenu(appmenu, MF_STRING, MENU_EXIT, "Exit");
- //SetMenuDefaultItem(appmenu, 0, FALSE);
-
- WNDCLASS wc;
- memset(&wc, 0, sizeof(wc));
- wc.hCursor = NULL; //LoadCursor(NULL, IDC_ARROW);
- wc.hIcon = appicon;
- wc.lpszMenuName = NULL;
- wc.lpszClassName = title;
- wc.style = 0;
- wc.hInstance = appinstance;
- wc.lpfnWndProc = handlemessages;
- wc.cbWndExtra = 0;
- wc.cbClsExtra = 0;
- wndclass = RegisterClass(&wc);
- if(!wndclass) fatal("failed registering window class");
-
- appwindow = CreateWindow(MAKEINTATOM(wndclass), title, 0, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, HWND_MESSAGE, NULL, appinstance, NULL);
- if(!appwindow) fatal("failed creating window");
-
- atexit(cleanupwindow);
-
- if(!setupsystemtray(WM_APP)) fatal("failed adding to system tray");
-}
-
-static char *parsecommandline(const char *src, vector<char *> &args)
-{
- char *buf = new char[strlen(src) + 1], *dst = buf;
- for(;;)
- {
- while(isspace(*src)) src++;
- if(!*src) break;
- args.add(dst);
- for(bool quoted = false; *src && (quoted || !isspace(*src)); src++)
- {
- if(*src != '"') *dst++ = *src;
- else if(dst > buf && src[-1] == '\\') dst[-1] = '"';
- else quoted = !quoted;
- }
- *dst++ = '\0';
- }
- args.add(NULL);
- return buf;
-}
-
-
-int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
-{
- vector<char *> args;
- char *buf = parsecommandline(GetCommandLine(), args);
- appinstance = hInst;
-#ifdef STANDALONE
- int standalonemain(int argc, char **argv);
- int status = standalonemain(args.length()-1, args.getbuf());
- #define main standalonemain
-#else
- SDL_SetMainReady();
- int status = SDL_main(args.length()-1, args.getbuf());
-#endif
- delete[] buf;
- exit(status);
- return 0;
-}
-
-void logoutfv(const char *fmt, va_list args)
-{
- if(appwindow)
- {
- logline &line = loglines.add();
- vformatstring(line.buf, fmt, args, sizeof(line.buf));
- if(logfile) writelog(logfile, line.buf);
- line.len = min(strlen(line.buf), sizeof(line.buf)-2);
- line.buf[line.len++] = '\n';
- line.buf[line.len] = '\0';
- if(outhandle) writeline(line);
- }
- else if(logfile) writelogv(logfile, fmt, args);
-}
-
-#else
-
void logoutfv(const char *fmt, va_list args)
{
FILE *f = getlogfile();
if(f) writelogv(f, fmt, args);
}
-#endif
-
static bool dedicatedserver = false;
bool isdedicatedserver() { return dedicatedserver; }
{
dedicatedserver = true;
logoutf("dedicated server started, waiting for clients...");
-#ifdef WIN32
- SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
- for(;;)
- {
- MSG msg;
- while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- {
- if(msg.message == WM_QUIT) exit(EXIT_SUCCESS);
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- serverslice(true, 5);
- }
-#else
for(;;) serverslice(true, 5);
-#endif
dedicatedserver = false;
}
fatal("%s", desc);
return false;
}
-
+
bool setuplistenserver(bool dedicated)
{
ENetAddress address = { ENET_HOST_ANY, enet_uint16(serverport <= 0 ? server::serverport() : serverport) };
void initserver(bool listen, bool dedicated)
{
- if(dedicated)
- {
-#ifdef WIN32
- setupwindow("Cube 2: Sauerbraten server");
-#endif
- }
-
execfile("server-init.cfg", false);
if(listen) setuplistenserver(dedicated);
if(serverhost) { conoutf(CON_ERROR, "listen server is already running"); return; }
allowupdatemaster = *usemaster>0 ? 1 : 0;
-
+
if(!setuplistenserver(false)) return;
-
+
updatemasterserver();
-
- conoutf("listen server started for %d clients%s", maxclients, allowupdatemaster ? " and listed with master server" : "");
+
+ conoutf("listen server started for %d clients%s", maxclients, allowupdatemaster ? " and listed with master server" : "");
}
COMMAND(startlistenserver, "i");
case 'u': setvar("serveruprate", atoi(opt+2)); return true;
case 'c': setvar("maxclients", atoi(opt+2)); return true;
case 'i': setsvar("serverip", opt+2); return true;
- case 'j': setvar("serverport", atoi(opt+2)); return true;
+ case 'j': setvar("serverport", atoi(opt+2)); return true;
case 'm': setsvar("mastername", opt+2); setvar("updatemaster", mastername[0] ? 1 : 0); return true;
#ifdef STANDALONE
case 'q': logoutf("Using home directory: %s", opt); sethomedir(opt+2); return true;
#ifdef STANDALONE
int main(int argc, char **argv)
-{
+{
setlogfile(NULL);
if(enet_initialize()<0) fatal("Unable to initialise network module");
atexit(enet_deinitialize);
#include "engine.h"
+#define PROTOCOL_VERSION 260 // bump when protocol changes, dpulicate
+
struct resolverthread
{
SDL_Thread *thread;
rt.query = NULL;
rt.starttime = 0;
SDL_UnlockMutex(resolvermutex);
-}
+}
void resolverclear()
{
else loopv(resolverthreads)
{
resolverthread &rt = resolverthreads[i];
- if(rt.query && totalmillis - rt.starttime > RESOLVERLIMIT)
+ if(rt.query && totalmillis - rt.starttime > RESOLVERLIMIT)
{
resolverstop(rt);
*name = rt.query;
resolved = true;
- }
+ }
}
SDL_UnlockMutex(resolvermutex);
return resolved;
SDL_CondSignal(querycond);
int starttime = SDL_GetTicks(), timeout = 0;
bool resolved = false;
- for(;;)
+ for(;;)
{
SDL_CondWaitTimeout(resultcond, resolvermutex, 250);
- loopv(resolverresults) if(resolverresults[i].query == name)
+ loopv(resolverresults) if(resolverresults[i].query == name)
{
address->host = resolverresults[i].address.host;
resolverresults.remove(i);
break;
}
if(resolved) break;
-
+
timeout = SDL_GetTicks() - starttime;
renderprogress(min(float(timeout)/RESOLVERLIMIT, 1.0f), text);
if(interceptkey(SDLK_ESCAPE)) timeout = RESOLVERLIMIT + 1;
- if(timeout > RESOLVERLIMIT) break;
+ if(timeout > RESOLVERLIMIT) break;
}
if(!resolved && timeout > RESOLVERLIMIT)
{
return -1;
}
-
+
struct pingattempts
{
enum { MAXATTEMPTS = 2 };
void clearattempts() { memset(attempts, 0, sizeof(attempts)); }
- void setoffset() { offset = 1 + rnd(0xFFFFFF); }
+ void setoffset() { offset = 1 + rnd(0xFFFFFF); }
int encodeping(int millis)
{
struct serverinfo : pingattempts
{
- enum
- {
+ enum
+ {
WAITING = INT_MAX,
MAXPINGS = 3
static bool compare(serverinfo *a, serverinfo *b)
{
- bool ac = server::servercompatible(a->name, a->sdesc, a->map, a->ping, a->attr, a->numplayers),
- bc = server::servercompatible(b->name, b->sdesc, b->map, b->ping, b->attr, b->numplayers);
+ bool ac = (a->attr.length() != 0) && (a->attr[0]==PROTOCOL_VERSION);
+ bool bc = (b->attr.length() != 0) && (b->attr[0]==PROTOCOL_VERSION);
if(ac > bc) return true;
if(bc > ac) return false;
if(a->keep > b->keep) return true;
void pingservers()
{
- if(pingsock == ENET_SOCKET_NULL)
+ if(pingsock == ENET_SOCKET_NULL)
{
pingsock = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
if(pingsock == ENET_SOCKET_NULL)
if(si.address.host == ENET_HOST_ANY) continue;
buildping(buf, ping, si);
enet_socket_send(pingsock, &si.address, &buf, 1);
-
+
si.checkdecay(servpingdecay);
}
if(searchlan)
}
lastinfo = totalmillis;
}
-
+
void checkresolver()
{
int resolving = 0;
serverinfo &si = *servers[i];
if(name == si.name)
{
- si.resolved = RESOLVED;
+ si.resolved = RESOLVED;
si.address.host = addr.host;
break;
}
ENetAddress addr;
uchar ping[MAXTRANS];
char text[MAXTRANS];
- buf.data = ping;
+ buf.data = ping;
buf.dataLength = sizeof(ping);
while(enet_socket_wait(pingsock, &events, 0) >= 0 && events)
{
int len = enet_socket_receive(pingsock, &addr, &buf, 1);
- if(len <= 0) return;
+ if(len <= 0) return;
ucharbuf p(ping, len);
int millis = getint(p);
serverinfo *si = NULL;
else if(!searchlan || !lanpings.checkattempt(millis, false)) continue;
else
{
- si = newserver(NULL, server::serverport(addr.port), addr.host);
+ si = newserver(NULL, server::serverport(addr.port), addr.host);
millis = lanpings.decodeping(millis);
}
int rtt = clamp(totalmillis - millis, 0, min(servpingdecay, totalmillis));
{
static int lastrefresh = 0;
if(lastrefresh==totalmillis) return;
- if(totalmillis - lastrefresh > 1000)
+ if(totalmillis - lastrefresh > 1000)
{
loopv(servers) servers[i]->reset();
lastreset = totalmillis;
while(reqlen > 0)
{
enet_uint32 events = ENET_SOCKET_WAIT_SEND;
- if(enet_socket_wait(sock, &events, 250) >= 0 && events)
+ if(enet_socket_wait(sock, &events, 250) >= 0 && events)
{
buf.data = (void *)req;
buf.dataLength = reqlen;
}
if(kept) f->printf("\n");
f->printf("// servers connected to are added here automatically\n\n");
- loopv(servers)
+ loopv(servers)
{
serverinfo *s = servers[i];
- if(!s->keep)
+ if(!s->keep)
{
if(s->password) f->printf("addserver %s %d %s\n", escapeid(s->name), s->port, escapestring(s->password));
else f->printf("addserver %s %d\n", escapeid(s->name), s->port);
return shadowmapcasters>0;
}
-
- bool flipdebug() const { return false; }
-
- void dodebug(int w, int h)
- {
- if(shadowmapcasters)
- {
- glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
- debugscissor(w, h);
- glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_FALSE);
- debugblurtiles(w, h);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- }
- }
} shadowmaptex;
void cleanshadowmap()
shadowmaptex.render(1<<shadowmapsize, 1<<shadowmapsize, blurshadowmap, blursmsigma/100.0f);
}
-
-VAR(debugsm, 0, 0, 1);
-
-void viewshadowmap()
-{
- if(!shadowmap) return;
- shadowmaptex.debug();
-}
-
bool hasslot(const soundslot *p, const vector<soundslot> &v) const
{
- return p >= v.getbuf() + slots && p < v.getbuf() + slots+numslots && slots+numslots < v.length();
+ return p >= v.getbuf() + slots && p < v.getbuf() + slots+numslots && slots+numslots < v.length();
}
int chooseslot(int flags) const
};
struct soundchannel
-{
+{
int id;
bool inuse;
- vec loc;
+ vec loc;
soundslot *slot;
- extentity *ent;
+ extentity *ent;
int radius, volume, pan, flags;
bool dirty;
DELETEP(musicstream);
}
-#ifdef WIN32
-#define AUDIODRIVER "directsound winmm"
-#else
#define AUDIODRIVER ""
-#endif
bool shouldinitaudio = true;
SVARF(audiodriver, AUDIODRIVER, { shouldinitaudio = true; initwarning("sound configuration", INIT_RESET, CHANGE_SOUND); });
VARF(usesound, 0, 1, 1, { shouldinitaudio = true; initwarning("sound configuration", INIT_RESET, CHANGE_SOUND); });
if(restorefallback)
{
restorefallback = false;
- #ifdef WIN32
- SDL_setenv("SDL_AUDIODRIVER", fallback, 1);
- #else
unsetenv("SDL_AUDIODRIVER");
- #endif
}
if(SDL_InitSubSystem(SDL_INIT_AUDIO) >= 0) return true;
conoutf(CON_ERROR, "sound init failed: %s", SDL_GetError());
conoutf(CON_ERROR, "sound init failed (SDL_mixer): %s", Mix_GetError());
return;
}
- Mix_AllocateChannels(soundchans);
+ Mix_AllocateChannels(soundchans);
maxchannels = soundchans;
nosound = false;
}
if(!musicrw) DELETEP(musicstream);
}
if(musicrw) music = Mix_LoadMUSType_RW(musicrw, MUS_NONE, 0);
- else music = Mix_LoadMUS(findfile(name, "rb"));
+ else music = Mix_LoadMUS(findfile(name, "rb"));
if(!music)
{
if(musicrw) { SDL_FreeRW(musicrw); musicrw = NULL; }
}
return music;
}
-
+
void startmusic(char *name, char *cmd)
{
if(nosound) return;
else
{
conoutf(CON_ERROR, "could not play music: %s", file);
- intret(0);
+ intret(0);
}
}
}
void clear_sound()
{
- closemumble();
if(nosound) return;
stopmusic();
chan.pan = pan;
chan.dirty = true;
return true;
-}
+}
void reclaimchannels()
{
void updatesounds()
{
- updatemumble();
if(nosound) return;
if(minimized && !minimizedsounds) stopsounds();
else
if(e.type==ET_SOUND) mapsounds.preloadsound(e.attr1);
}
}
-
+
int playsound(int n, const vec *loc, extentity *ent, int flags, int loops, int fade, int chanid, int radius, int expire)
{
if(nosound || !soundvol || (minimized && !minimizedsounds)) return -1;
Mix_HaltChannel(chanid);
freechannel(chanid);
}
- return -1;
+ return -1;
}
}
if(!slot.sample->chunk && !slot.sample->load()) return -1;
if(dbgsound) conoutf(CON_DEBUG, "sound: %s", slot.sample->name);
-
+
chanid = -1;
loopv(channels) if(!channels[i].inuse) { chanid = i; break; }
if(chanid < 0 && channels.length() < maxchannels) chanid = channels.length();
soundchannel &chan = newchannel(chanid, &slot, loc, ent, flags, radius);
updatechannel(chan);
int playing = -1;
- if(fade)
+ if(fade)
{
Mix_Volume(chanid, chan.volume);
playing = expire >= 0 ? Mix_FadeInChannelTimed(chanid, slot.sample->chunk, loops, fade, expire) : Mix_FadeInChannel(chanid, slot.sample->chunk, loops, fade);
}
else playing = expire >= 0 ? Mix_PlayChannelTimed(chanid, slot.sample->chunk, loops, expire) : Mix_PlayChannel(chanid, slot.sample->chunk, loops);
- if(playing >= 0) syncchannel(chan);
+ if(playing >= 0) syncchannel(chan);
else freechannel(chanid);
return playing;
}
return true;
}
-int playsoundname(const char *s, const vec *loc, int vol, int flags, int loops, int fade, int chanid, int radius, int expire)
-{
+int playsoundname(const char *s, const vec *loc, int vol, int flags, int loops, int fade, int chanid, int radius, int expire)
+{
if(!vol) vol = 100;
int id = gamesounds.findsound(s, vol);
if(id < 0) id = gamesounds.addsound(s, vol);
void resetsound()
{
clearchanges(CHANGE_SOUND);
- if(!nosound)
+ if(!nosound)
{
cleanupsamples();
if(music)
}
COMMAND(resetsound, "");
-
-#ifdef WIN32
-
-#include <wchar.h>
-
-#else
-
-#include <unistd.h>
-
-#ifdef _POSIX_SHARED_MEMORY_OBJECTS
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <wchar.h>
-#endif
-
-#endif
-
-#if defined(WIN32) || defined(_POSIX_SHARED_MEMORY_OBJECTS)
-struct MumbleInfo
-{
- int version, timestamp;
- vec pos, front, top;
- wchar_t name[256];
-};
-#endif
-
-#ifdef WIN32
-static HANDLE mumblelink = NULL;
-static MumbleInfo *mumbleinfo = NULL;
-#define VALID_MUMBLELINK (mumblelink && mumbleinfo)
-#elif defined(_POSIX_SHARED_MEMORY_OBJECTS)
-static int mumblelink = -1;
-static MumbleInfo *mumbleinfo = (MumbleInfo *)-1;
-#define VALID_MUMBLELINK (mumblelink >= 0 && mumbleinfo != (MumbleInfo *)-1)
-#endif
-
-#ifdef VALID_MUMBLELINK
-VARFP(mumble, 0, 1, 1, { if(mumble) initmumble(); else closemumble(); });
-#else
-VARFP(mumble, 0, 0, 1, { if(mumble) initmumble(); else closemumble(); });
-#endif
-
-void initmumble()
-{
- if(!mumble) return;
-#ifdef VALID_MUMBLELINK
- if(VALID_MUMBLELINK) return;
-
- #ifdef WIN32
- mumblelink = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "MumbleLink");
- if(mumblelink)
- {
- mumbleinfo = (MumbleInfo *)MapViewOfFile(mumblelink, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(MumbleInfo));
- if(mumbleinfo) wcsncpy(mumbleinfo->name, L"Sauerbraten", 256);
- }
- #elif defined(_POSIX_SHARED_MEMORY_OBJECTS)
- defformatstring(shmname, "/MumbleLink.%d", getuid());
- mumblelink = shm_open(shmname, O_RDWR, 0);
- if(mumblelink >= 0)
- {
- mumbleinfo = (MumbleInfo *)mmap(NULL, sizeof(MumbleInfo), PROT_READ|PROT_WRITE, MAP_SHARED, mumblelink, 0);
- if(mumbleinfo != (MumbleInfo *)-1) wcsncpy(mumbleinfo->name, L"Sauerbraten", 256);
- }
- #endif
- if(!VALID_MUMBLELINK) closemumble();
-#else
- conoutf(CON_ERROR, "Mumble positional audio is not available on this platform.");
-#endif
-}
-
-void closemumble()
-{
-#ifdef WIN32
- if(mumbleinfo) { UnmapViewOfFile(mumbleinfo); mumbleinfo = NULL; }
- if(mumblelink) { CloseHandle(mumblelink); mumblelink = NULL; }
-#elif defined(_POSIX_SHARED_MEMORY_OBJECTS)
- if(mumbleinfo != (MumbleInfo *)-1) { munmap(mumbleinfo, sizeof(MumbleInfo)); mumbleinfo = (MumbleInfo *)-1; }
- if(mumblelink >= 0) { close(mumblelink); mumblelink = -1; }
-#endif
-}
-
-static inline vec mumblevec(const vec &v, bool pos = false)
-{
- // change from X left, Z up, Y forward to X right, Y up, Z forward
- // 8 cube units = 1 meter
- vec m(-v.x, v.z, v.y);
- if(pos) m.div(8);
- return m;
-}
-
-void updatemumble()
-{
-#ifdef VALID_MUMBLELINK
- if(!VALID_MUMBLELINK) return;
-
- static int timestamp = 0;
-
- mumbleinfo->version = 1;
- mumbleinfo->timestamp = ++timestamp;
-
- mumbleinfo->pos = mumblevec(player->o, true);
- mumbleinfo->front = mumblevec(vec(RAD*player->yaw, RAD*player->pitch));
- mumbleinfo->top = mumblevec(vec(RAD*player->yaw, RAD*(player->pitch+90)));
-#endif
-}
-
void del(int start, int count)
{
if(!text) return;
- if(start < 0) { count += start; start = 0; }
+ if(start < 0) { count += start; start = 0; }
if(count <= 0 || start >= len) return;
if(start + count > len) count = len - start - 1;
memmove(&text[start], &text[start+count], len + 1 - (start + count));
}
}
};
-
-struct editor
+
+struct editor
{
int mode; //editor mode - 1= keep while focused, 2= keep while used in gui, 3= keep forever (i.e. until mode changes)
bool active, rendered;
int cx, cy; // cursor position - ensured to be valid after a region() or currentline()
int mx, my; // selection mark, mx=-1 if following cursor - avoid direct access, instead use region()
int maxx, maxy; // maxy=-1 if unlimited lines, 1 if single line editor
-
+
int scrolly; // vertical scroll offset
-
+
bool linewrap;
int pixelwidth; // required for up/down/hit/draw/bounds
int pixelheight; // -1 for variable sized, i.e. from bounds()
-
+
vector<editline> lines; // MUST always contain at least one line!
-
- editor(const char *name, int mode, const char *initval) :
+
+ editor(const char *name, int mode, const char *initval) :
mode(mode), active(true), rendered(false), name(newstring(name)), filename(NULL),
cx(0), cy(0), mx(-1), maxx(-1), maxy(-1), scrolly(0), linewrap(false), pixelwidth(-1), pixelheight(-1)
{
//printf("editor %08x '%s'\n", this, name);
lines.add().set(initval ? initval : "");
}
-
+
~editor()
{
//printf("~editor %08x '%s'\n", this, name);
DELETEA(filename);
clear(NULL);
}
-
+
void clear(const char *init = "")
{
cx = cy = 0;
lines.shrink(0);
if(init) lines.add().set(init);
}
-
+
void setfile(const char *fname)
{
- DELETEA(filename);
+ DELETEA(filename);
if(fname) filename = newstring(fname);
}
-
+
void load()
{
if(!filename) return;
clear(NULL);
stream *file = openutf8file(filename, "r");
- if(file)
+ if(file)
{
while(lines.add().read(file, maxx) && (maxy < 0 || lines.length() <= maxy));
lines.pop().clear();
}
if(lines.empty()) lines.add().set("");
}
-
+
void save()
{
if(!filename) return;
loopv(lines) file->putline(lines[i].text);
delete file;
}
-
- void mark(bool enable)
+
+ void mark(bool enable)
{
mx = (enable) ? cx : -1;
my = cy;
}
-
+
void selectall()
{
mx = my = INT_MAX;
cx = cy = 0;
}
-
+
// constrain results to within buffer - s=start, e=end, return true if a selection range
// also ensures that cy is always within lines[] and cx is valid
bool region(int &sx, int &sy, int &ex, int &ey)
{
- int n = lines.length();
+ int n = lines.length();
ASSERT(n != 0);
if(cy < 0) cy = 0; else if(cy >= n) cy = n-1;
int len = lines[cy].len;
if(cx < 0) cx = 0; else if(cx > len) cx = len;
- if(mx >= 0)
+ if(mx >= 0)
{
if(my < 0) my = 0; else if(my >= n) my = n-1;
len = lines[my].len;
ex = cx;
ey = cy;
if(sy > ey) { swap(sy, ey); swap(sx, ex); }
- else if(sy==ey && sx > ex) swap(sx, ex);
+ else if(sy==ey && sx > ex) swap(sx, ex);
return (sx != ex) || (sy != ey);
}
-
+
bool region() { int sx, sy, ex, ey; return region(sx, sy, ex, ey); }
// also ensures that cy is always within lines[] and cx is valid
editline ¤tline()
{
- int n = lines.length();
+ int n = lines.length();
ASSERT(n != 0);
if(cy < 0) cy = 0; else if(cy >= n) cy = n-1;
if(cx < 0) cx = 0; else if(cx > lines[cy].len) cx = lines[cy].len;
loopi(count) lines[start+i].clear();
lines.remove(start, count);
}
-
+
bool del() // removes the current selection (if any)
{
int sx, sy, ex, ey;
- if(!region(sx, sy, ex, ey))
- {
- mark(false);
- return false;
+ if(!region(sx, sy, ex, ey))
+ {
+ mark(false);
+ return false;
}
- if(sy == ey)
+ if(sy == ey)
{
if(sx == 0 && ex == lines[ey].len) removelines(sy, 1);
else lines[sy].del(sx, ex - sx);
}
return true;
}
-
- void insert(char ch)
+
+ void insert(char ch)
{
del();
editline ¤t = currentline();
- if(ch == '\n')
+ if(ch == '\n')
{
if(maxy == -1 || cy < maxy-1)
{
}
else current.chop(cx);
cx = 0;
- }
+ }
else
{
int len = current.len;
while(*s) insert(*s++);
}
- void insertallfrom(editor *b)
- {
+ void insertallfrom(editor *b)
+ {
if(b==this) return;
del();
-
- if(b->lines.length() == 1 || maxy == 1)
+
+ if(b->lines.length() == 1 || maxy == 1)
{
editline ¤t = currentline();
- char *str = b->lines[0].text;
+ char *str = b->lines[0].text;
int slen = b->lines[0].len;
if(maxx >= 0 && b->lines[0].len + cx > maxx) slen = maxx-cx;
- if(slen > 0)
+ if(slen > 0)
{
int len = current.len;
if(maxx >= 0 && slen + cx + len > maxx) len = max(0, maxx-(cx+slen));
- current.insert(str, cx, slen);
+ current.insert(str, cx, slen);
cx += slen;
}
- }
- else
+ }
+ else
{
- loopv(b->lines)
- {
- if(!i)
+ loopv(b->lines)
+ {
+ if(!i)
{
lines[cy++].append(b->lines[i].text);
}
void key(int code)
{
- switch(code)
+ switch(code)
{
case SDLK_UP:
- if(linewrap)
+ if(linewrap)
{
- int x, y;
+ int x, y;
char *str = currentline().text;
text_pos(str, cx+1, x, y, pixelwidth);
if(y > 0) { cx = text_visible(str, x, y-FONTH, pixelwidth); break; }
cy--;
break;
case SDLK_DOWN:
- if(linewrap)
+ if(linewrap)
{
int x, y, width, height;
char *str = currentline().text;
if(!del())
{
editline ¤t = currentline();
- if(cx > 0) current.del(--cx, 1);
+ if(cx > 0) current.del(--cx, 1);
else if(cy > 0)
{ //combine with previous line
cx = lines[cy-1].len;
case SDLK_LSHIFT:
case SDLK_RSHIFT:
break;
- case SDLK_RETURN:
+ case SDLK_RETURN:
insert('\n');
break;
case SDLK_TAB:
int width, height;
text_bounds(lines[i].text, width, height, maxwidth);
if(h + height > pixelheight) break;
-
- if(hity >= h && hity <= h+height)
+
+ if(hity >= h && hity <= h+height)
{
- int x = text_visible(lines[i].text, hitx, hity-h, maxwidth);
+ int x = text_visible(lines[i].text, hitx, hity-h, maxwidth);
if(dragged) { mx = x; my = i; } else { cx = x; cy = i; };
break;
}
void draw(int x, int y, int color, bool hit)
{
int maxwidth = linewrap?pixelwidth:-1;
-
+
int sx, sy, ex, ey;
bool selection = region(sx, sy, ex, ey);
-
+
// fix scrolly so that <cx, cy> is always on screen
if(cy < scrolly) scrolly = cy;
- else
+ else
{
if(scrolly < 0) scrolly = 0;
int h = 0;
h += height;
}
}
-
+
if(selection)
{
// convert from cursor coords into pixel coords
for(int i = scrolly; i < maxy; i++)
{
int width, height;
- text_bounds(lines[i].text, width, height, maxwidth);
+ text_bounds(lines[i].text, width, height, maxwidth);
if(h + height > pixelheight) { maxy = i; break; }
if(i == sy) psy += h;
if(i == ey) { pey += h; break; }
h += height;
}
maxy--;
-
- if(ey >= scrolly && sy <= maxy)
+
+ if(ey >= scrolly && sy <= maxy)
{
// crop top/bottom within window
if(sy < scrolly) { sy = scrolly; psy = 0; psx = 0; }
gle::colorub(0xA0, 0x80, 0x80);
gle::defvertex(2);
gle::begin(GL_QUADS);
- if(psy == pey)
+ if(psy == pey)
{
gle::attribf(x+psx, y+psy);
gle::attribf(x+pex, y+psy);
gle::attribf(x+pex, y+pey+FONTH);
gle::attribf(x+psx, y+pey+FONTH);
- }
- else
+ }
+ else
{ gle::attribf(x+psx, y+psy);
gle::attribf(x+psx, y+psy+FONTH);
gle::attribf(x+pixelwidth, y+psy+FONTH);
gle::attribf(x+pixelwidth, y+psy);
- if(pey-psy > FONTH)
+ if(pey-psy > FONTH)
{
gle::attribf(x, y+psy+FONTH);
gle::attribf(x+pixelwidth, y+psy+FONTH);
hudshader->set();
}
}
-
+
int h = 0;
for(int i = scrolly; i < lines.length(); i++)
{
int width, height;
text_bounds(lines[i].text, width, height, maxwidth);
if(h + height > pixelheight) break;
-
+
draw_text(lines[i].text, x, y+h, color>>16, (color>>8)&0xFF, color&0xFF, 0xFF, hit&&(cy==i)?cx:-1, maxwidth);
if(linewrap && height > FONTH) // line wrap indicator
- {
+ {
hudnotextureshader->set();
gle::colorub(0x80, 0xA0, 0x80);
gle::defvertex(2);
static editor *currentfocus() { return editors.length() ? editors.last() : NULL; }
-static void readyeditors()
+static void readyeditors()
{
loopv(editors) editors[i]->active = (editors[i]->mode==EDITORFOREVER);
}
-static void flusheditors()
+static void flusheditors()
{
- loopvrev(editors) if(!editors[i]->active)
+ loopvrev(editors) if(!editors[i]->active)
{
editor *e = editors.remove(i);
DELETEP(e);
}
}
-static editor *useeditor(const char *name, int mode, bool focus, const char *initval = NULL)
+static editor *useeditor(const char *name, int mode, bool focus, const char *initval = NULL)
{
- loopv(editors) if(strcmp(editors[i]->name, name) == 0)
+ loopv(editors) if(strcmp(editors[i]->name, name) == 0)
{
editor *e = editors[i];
if(focus) { editors.add(e); editors.remove(i); } // re-position as last
return e;
}
editor *e = new editor(name, mode, initval);
- if(focus) editors.add(e); else editors.insert(0, e);
+ if(focus) editors.add(e); else editors.insert(0, e);
return e;
}
ICOMMAND(textlist, "", (), // @DEBUG return list of all the editors
vector<char> s;
loopv(editors)
- {
+ {
if(i > 0) s.put(", ", 2);
s.put(editors[i]->name, strlen(editors[i]->name));
}
else intret(top->mode);
);
TEXTCOMMAND(textsave, "s", (char *file), // saves the topmost (filename is optional)
- if(*file) top->setfile(path(file, true));
+ if(*file) top->setfile(path(file, true));
top->save();
-);
+);
TEXTCOMMAND(textload, "s", (char *file), // loads into the topmost editor, returns filename if no args
if(*file)
{
e->load();
}
});
-
+
#define PASTEBUFFER "#pastebuffer"
TEXTCOMMAND(textcopy, "", (), editor *b = useeditor(PASTEBUFFER, EDITORFOREVER, false); top->copyselectionto(b););
return v;
}
-VAR(usedds, 0, 1, 1);
-VAR(dbgdds, 0, 0, 1);
-VAR(scaledds, 0, 2, 4);
-
static bool texturedata(ImageData &d, const char *tname, Slot::Tex *tex = NULL, bool msg = true, int *compress = NULL, int *wrap = NULL)
{
const char *cmds = NULL, *file = tname;
}
int flen = strlen(file);
- bool raw = !usedds || !compress, dds = false, guess = false;
+ bool raw = !compress, guess = false;
for(const char *pcmds = cmds; pcmds;)
{
#define PARSETEXCOMMANDS(cmds) \
else arg[i]++; \
}
PARSETEXCOMMANDS(pcmds);
- if(matchstring(cmd, len, "dds")) dds = true;
- else if(matchstring(cmd, len, "thumbnail"))
+ if(matchstring(cmd, len, "thumbnail"))
{
raw = true;
guess = flen >= 4 && !strchr(file+flen-4, '.');
if(msg) renderprogress(loadprogress, file);
- if(flen >= 4 && (!strcasecmp(file + flen - 4, ".dds") || (dds && !raw)))
- {
- string dfile;
- copystring(dfile, file);
- memcpy(dfile + flen - 4, ".dds", 4);
- if(!loaddds(dfile, d, raw ? 1 : (dds ? 0 : -1)) && (!dds || raw))
- {
- if(msg) conoutf(CON_ERROR, "could not load texture %s", dfile);
- return false;
- }
- if(d.data && !d.compressed && !dds && compress) *compress = scaledds;
- }
-
if(!d.data)
{
SDL_Surface *s = NULL;
}
else if(matchstring(cmd, len, "premul")) texpremul(d);
else if(matchstring(cmd, len, "agrad")) texagrad(d, atof(arg[0]), atof(arg[1]), atof(arg[2]), atof(arg[3]));
- else if(matchstring(cmd, len, "compress") || matchstring(cmd, len, "dds"))
+ else if(matchstring(cmd, len, "compress"))
{
int scale = atoi(arg[0]);
- if(scale <= 0) scale = scaledds;
+ if(scale <= 0) scale = 2;
if(compress) *compress = scale;
}
else if(matchstring(cmd, len, "nocompress"))
loadprogress = 0;
}
-enum
-{
- DDSD_CAPS = 0x00000001,
- DDSD_HEIGHT = 0x00000002,
- DDSD_WIDTH = 0x00000004,
- DDSD_PITCH = 0x00000008,
- DDSD_PIXELFORMAT = 0x00001000,
- DDSD_MIPMAPCOUNT = 0x00020000,
- DDSD_LINEARSIZE = 0x00080000,
- DDSD_BACKBUFFERCOUNT = 0x00800000,
- DDPF_ALPHAPIXELS = 0x00000001,
- DDPF_FOURCC = 0x00000004,
- DDPF_INDEXED = 0x00000020,
- DDPF_ALPHA = 0x00000002,
- DDPF_RGB = 0x00000040,
- DDPF_COMPRESSED = 0x00000080,
- DDPF_LUMINANCE = 0x00020000,
- DDSCAPS_COMPLEX = 0x00000008,
- DDSCAPS_TEXTURE = 0x00001000,
- DDSCAPS_MIPMAP = 0x00400000,
- DDSCAPS2_CUBEMAP = 0x00000200,
- DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400,
- DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800,
- DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000,
- DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000,
- DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000,
- DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000,
- DDSCAPS2_VOLUME = 0x00200000,
- FOURCC_DXT1 = 0x31545844,
- FOURCC_DXT2 = 0x32545844,
- FOURCC_DXT3 = 0x33545844,
- FOURCC_DXT4 = 0x34545844,
- FOURCC_DXT5 = 0x35545844,
- FOURCC_ATI1 = 0x31495441,
- FOURCC_ATI2 = 0x32495441
-};
-
-struct DDCOLORKEY { uint dwColorSpaceLowValue, dwColorSpaceHighValue; };
-struct DDPIXELFORMAT
-{
- uint dwSize, dwFlags, dwFourCC;
- union { uint dwRGBBitCount, dwYUVBitCount, dwZBufferBitDepth, dwAlphaBitDepth, dwLuminanceBitCount, dwBumpBitCount, dwPrivateFormatBitCount; };
- union { uint dwRBitMask, dwYBitMask, dwStencilBitDepth, dwLuminanceBitMask, dwBumpDuBitMask, dwOperations; };
- union { uint dwGBitMask, dwUBitMask, dwZBitMask, dwBumpDvBitMask; struct { ushort wFlipMSTypes, wBltMSTypes; } MultiSampleCaps; };
- union { uint dwBBitMask, dwVBitMask, dwStencilBitMask, dwBumpLuminanceBitMask; };
- union { uint dwRGBAlphaBitMask, dwYUVAlphaBitMask, dwLuminanceAlphaBitMask, dwRGBZBitMask, dwYUVZBitMask; };
-
-};
-struct DDSCAPS2 { uint dwCaps, dwCaps2, dwCaps3, dwCaps4; };
-struct DDSURFACEDESC2
-{
- uint dwSize, dwFlags, dwHeight, dwWidth;
- union { int lPitch; uint dwLinearSize; };
- uint dwBackBufferCount;
- union { uint dwMipMapCount, dwRefreshRate, dwSrcVBHandle; };
- uint dwAlphaBitDepth, dwReserved, lpSurface;
- union { DDCOLORKEY ddckCKDestOverlay; uint dwEmptyFaceColor; };
- DDCOLORKEY ddckCKDestBlt, ddckCKSrcOverlay, ddckCKSrcBlt;
- union { DDPIXELFORMAT ddpfPixelFormat; uint dwFVF; };
- DDSCAPS2 ddsCaps;
- uint dwTextureStage;
-};
-
-#define DECODEDDS(name, dbpp, initblock, writeval, nextval) \
-static void name(ImageData &s) \
-{ \
- ImageData d(s.w, s.h, dbpp); \
- uchar *dst = d.data; \
- const uchar *src = s.data; \
- for(int by = 0; by < s.h; by += s.align) \
- { \
- for(int bx = 0; bx < s.w; bx += s.align, src += s.bpp) \
- { \
- int maxy = min(d.h - by, s.align), maxx = min(d.w - bx, s.align); \
- initblock; \
- loop(y, maxy) \
- { \
- int x; \
- for(x = 0; x < maxx; ++x) \
- { \
- writeval; \
- nextval; \
- dst += d.bpp; \
- } \
- for(; x < s.align; ++x) { nextval; } \
- dst += d.pitch - maxx*d.bpp; \
- } \
- dst += maxx*d.bpp - maxy*d.pitch; \
- } \
- dst += (s.align-1)*d.pitch; \
- } \
- s.replace(d); \
-}
-
-DECODEDDS(decodedxt1, s.compressed == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ? 4 : 3,
- ushort color0 = lilswap(*(const ushort *)src);
- ushort color1 = lilswap(*(const ushort *)&src[2]);
- uint bits = lilswap(*(const uint *)&src[4]);
- bvec4 rgba[4];
- rgba[0] = bvec4(bvec::from565(color0), 0xFF);
- rgba[1] = bvec4(bvec::from565(color1), 0xFF);
- if(color0 > color1)
- {
- rgba[2].lerp(rgba[0], rgba[1], 2, 1, 3);
- rgba[3].lerp(rgba[0], rgba[1], 1, 2, 3);
- }
- else
- {
- rgba[2].lerp(rgba[0], rgba[1], 1, 1, 2);
- rgba[3] = bvec4(0, 0, 0, 0);
- }
-,
- memcpy(dst, rgba[bits&3].v, d.bpp);
-,
- bits >>= 2;
-);
-
-DECODEDDS(decodedxt3, 4,
- ullong alpha = lilswap(*(const ullong *)src);
- ushort color0 = lilswap(*(const ushort *)&src[8]);
- ushort color1 = lilswap(*(const ushort *)&src[10]);
- uint bits = lilswap(*(const uint *)&src[12]);
- bvec rgb[4];
- rgb[0] = bvec::from565(color0);
- rgb[1] = bvec::from565(color1);
- rgb[2].lerp(rgb[0], rgb[1], 2, 1, 3);
- rgb[3].lerp(rgb[0], rgb[1], 1, 2, 3);
-,
- memcpy(dst, rgb[bits&3].v, 3);
- dst[3] = ((alpha&0xF)*1088 + 32) >> 6;
-,
- bits >>= 2;
- alpha >>= 4;
-);
-
-static inline void decodealpha(uchar alpha0, uchar alpha1, uchar alpha[8])
-{
- alpha[0] = alpha0;
- alpha[1] = alpha1;
- if(alpha0 > alpha1)
- {
- alpha[2] = (6*alpha0 + alpha1)/7;
- alpha[3] = (5*alpha0 + 2*alpha1)/7;
- alpha[4] = (4*alpha0 + 3*alpha1)/7;
- alpha[5] = (3*alpha0 + 4*alpha1)/7;
- alpha[6] = (2*alpha0 + 5*alpha1)/7;
- alpha[7] = (alpha0 + 6*alpha1)/7;
- }
- else
- {
- alpha[2] = (4*alpha0 + alpha1)/5;
- alpha[3] = (3*alpha0 + 2*alpha1)/5;
- alpha[4] = (2*alpha0 + 3*alpha1)/5;
- alpha[5] = (alpha0 + 4*alpha1)/5;
- alpha[6] = 0;
- alpha[7] = 0xFF;
- }
-}
-
-DECODEDDS(decodedxt5, 4,
- uchar alpha[8];
- decodealpha(src[0], src[1], alpha);
- ullong alphabits = lilswap(*(const ushort *)&src[2]) + ((ullong)lilswap(*(const uint *)&src[4]) << 16);
- ushort color0 = lilswap(*(const ushort *)&src[8]);
- ushort color1 = lilswap(*(const ushort *)&src[10]);
- uint bits = lilswap(*(const uint *)&src[12]);
- bvec rgb[4];
- rgb[0] = bvec::from565(color0);
- rgb[1] = bvec::from565(color1);
- rgb[2].lerp(rgb[0], rgb[1], 2, 1, 3);
- rgb[3].lerp(rgb[0], rgb[1], 1, 2, 3);
-,
- memcpy(dst, rgb[bits&3].v, 3);
- dst[3] = alpha[alphabits&7];
-,
- bits >>= 2;
- alphabits >>= 3;
-);
-
-DECODEDDS(decodergtc1, 1,
- uchar red[8];
- decodealpha(src[0], src[1], red);
- ullong redbits = lilswap(*(const ushort *)&src[2]) + ((ullong)lilswap(*(const uint *)&src[4]) << 16);
-,
- dst[0] = red[redbits&7];
-,
- redbits >>= 3;
-);
-
-DECODEDDS(decodergtc2, 2,
- uchar red[8];
- decodealpha(src[0], src[1], red);
- ullong redbits = lilswap(*(const ushort *)&src[2]) + ((ullong)lilswap(*(const uint *)&src[4]) << 16);
- uchar green[8];
- decodealpha(src[8], src[9], green);
- ullong greenbits = lilswap(*(const ushort *)&src[10]) + ((ullong)lilswap(*(const uint *)&src[12]) << 16);
-,
- dst[0] = red[redbits&7];
- dst[1] = green[greenbits&7];
-,
- redbits >>= 3;
- greenbits >>= 3;
-);
-
-bool loaddds(const char *filename, ImageData &image, int force)
-{
- stream *f = openfile(filename, "rb");
- if(!f) return false;
- GLenum format = GL_FALSE;
- uchar magic[4];
- if(f->read(magic, 4) != 4 || memcmp(magic, "DDS ", 4)) { delete f; return false; }
- DDSURFACEDESC2 d;
- if(f->read(&d, sizeof(d)) != sizeof(d)) { delete f; return false; }
- lilswap((uint *)&d, sizeof(d)/sizeof(uint));
- if(d.dwSize != sizeof(DDSURFACEDESC2) || d.ddpfPixelFormat.dwSize != sizeof(DDPIXELFORMAT)) { delete f; return false; }
- bool supported = false;
- if(d.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
- {
- switch(d.ddpfPixelFormat.dwFourCC)
- {
- case FOURCC_DXT1:
- if((supported = hasS3TC) || force) format = d.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS ? GL_COMPRESSED_RGBA_S3TC_DXT1_EXT : GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
- break;
- case FOURCC_DXT2:
- case FOURCC_DXT3:
- if((supported = hasS3TC) || force) format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
- break;
- case FOURCC_DXT4:
- case FOURCC_DXT5:
- if((supported = hasS3TC) || force) format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
- break;
- case FOURCC_ATI1:
- if((supported = hasRGTC) || force) format = GL_COMPRESSED_RED_RGTC1;
- else if((supported = hasLATC)) format = GL_COMPRESSED_LUMINANCE_LATC1_EXT;
- break;
- case FOURCC_ATI2:
- if((supported = hasRGTC) || force) format = GL_COMPRESSED_RG_RGTC2;
- else if((supported = hasLATC)) format = GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT;
- break;
- }
- }
- if(!format || (!supported && !force)) { delete f; return false; }
- if(dbgdds) conoutf(CON_DEBUG, "%s: format 0x%X, %d x %d, %d mipmaps", filename, format, d.dwWidth, d.dwHeight, d.dwMipMapCount);
- int bpp = 0;
- switch(format)
- {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: bpp = 8; break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: bpp = 16; break;
- case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
- case GL_COMPRESSED_RED_RGTC1: bpp = 8; break;
- case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
- case GL_COMPRESSED_RG_RGTC2: bpp = 16; break;
- }
- image.setdata(NULL, d.dwWidth, d.dwHeight, bpp, !supported || force > 0 ? 1 : d.dwMipMapCount, 4, format);
- size_t size = image.calcsize();
- if(f->read(image.data, size) != size) { delete f; image.cleanup(); return false; }
- delete f;
- if(!supported || force > 0) switch(format)
- {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- decodedxt1(image);
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
- decodedxt3(image);
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- decodedxt5(image);
- break;
- case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
- case GL_COMPRESSED_RED_RGTC1:
- decodergtc1(image);
- break;
- case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
- case GL_COMPRESSED_RG_RGTC2:
- decodergtc2(image);
- break;
- }
- return true;
-}
-
-void gendds(char *infile, char *outfile)
-{
- if(!hasS3TC || usetexcompress <= 1) { conoutf(CON_ERROR, "OpenGL driver does not support S3TC texture compression"); return; }
-
- glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST);
-
- defformatstring(cfile, "<compress>%s", infile);
- extern void reloadtex(char *name);
- Texture *t = textures.access(path(cfile));
- if(t) reloadtex(cfile);
- t = textureload(cfile);
- if(t==notexture) { conoutf(CON_ERROR, "failed loading %s", infile); return; }
-
- glBindTexture(GL_TEXTURE_2D, t->id);
- GLint compressed = 0, format = 0, width = 0, height = 0;
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED, &compressed);
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
- glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
-
- if(!compressed) { conoutf(CON_ERROR, "failed compressing %s", infile); return; }
- int fourcc = 0;
- switch(format)
- {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: fourcc = FOURCC_DXT1; conoutf("compressed as DXT1"); break;
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: fourcc = FOURCC_DXT1; conoutf("compressed as DXT1a"); break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: fourcc = FOURCC_DXT3; conoutf("compressed as DXT3"); break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: fourcc = FOURCC_DXT5; conoutf("compressed as DXT5"); break;
- case GL_COMPRESSED_LUMINANCE_LATC1_EXT:
- case GL_COMPRESSED_RED_RGTC1: fourcc = FOURCC_ATI1; conoutf("compressed as ATI1"); break;
- case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT:
- case GL_COMPRESSED_RG_RGTC2: fourcc = FOURCC_ATI2; conoutf("compressed as ATI2"); break;
- default:
- conoutf(CON_ERROR, "failed compressing %s: unknown format: 0x%X", infile, format); break;
- return;
- }
-
- if(!outfile[0])
- {
- static string buf;
- copystring(buf, infile);
- int len = strlen(buf);
- if(len > 4 && buf[len-4]=='.') memcpy(&buf[len-4], ".dds", 4);
- else concatstring(buf, ".dds");
- outfile = buf;
- }
-
- stream *f = openfile(path(outfile, true), "wb");
- if(!f) { conoutf(CON_ERROR, "failed writing to %s", outfile); return; }
-
- int csize = 0;
- for(int lw = width, lh = height, level = 0;;)
- {
- GLint size = 0;
- glGetTexLevelParameteriv(GL_TEXTURE_2D, level++, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &size);
- csize += size;
- if(max(lw, lh) <= 1) break;
- if(lw > 1) lw /= 2;
- if(lh > 1) lh /= 2;
- }
-
- DDSURFACEDESC2 d;
- memset(&d, 0, sizeof(d));
- d.dwSize = sizeof(DDSURFACEDESC2);
- d.dwWidth = width;
- d.dwHeight = height;
- d.dwLinearSize = csize;
- d.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_LINEARSIZE | DDSD_MIPMAPCOUNT;
- d.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
- d.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
- d.ddpfPixelFormat.dwFlags = DDPF_FOURCC | (alphaformat(uncompressedformat(format)) ? DDPF_ALPHAPIXELS : 0);
- d.ddpfPixelFormat.dwFourCC = fourcc;
-
- uchar *data = new uchar[csize], *dst = data;
- for(int lw = width, lh = height;;)
- {
- GLint size;
- glGetTexLevelParameteriv(GL_TEXTURE_2D, d.dwMipMapCount, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &size);
- glGetCompressedTexImage_(GL_TEXTURE_2D, d.dwMipMapCount++, dst);
- dst += size;
- if(max(lw, lh) <= 1) break;
- if(lw > 1) lw /= 2;
- if(lh > 1) lh /= 2;
- }
-
- lilswap((uint *)&d, sizeof(d)/sizeof(uint));
-
- f->write("DDS ", 4);
- f->write(&d, sizeof(d));
- f->write(data, csize);
- delete f;
-
- delete[] data;
-
- conoutf("wrote DDS file %s", outfile);
-
- setuptexcompress();
-}
-COMMAND(gendds, "ss");
-
void writepngchunk(stream *f, const char *type, uchar *data = NULL, uint len = 0)
{
f->putbig<uint>(len);
extern void savepng(const char *filename, ImageData &image, bool flip = false);
extern void savetga(const char *filename, ImageData &image, bool flip = false);
-extern bool loaddds(const char *filename, ImageData &image, int force = 0);
extern bool loadimage(const char *filename, ImageData &image);
extern MSlot &lookupmaterialslot(int slot, bool load = true);
{
Reflection &ref = reflections[i];
++ref.age;
- //~if(ref.height>=0 && !ref.age && ref.matsurfs.length())
- //~{
- //~/***/ref.matsurfs.setsize(0);
- //~}
}
if(waterfallrefract)
{
Reflection &ref = waterfallrefraction;
++ref.age;
- //~if(ref.height>=0 && !ref.age && ref.matsurfs.length())
- //~{
- //~/***/ref.matsurfs.setsize(0);
- //~}
}
if((editmode && showmat && !drawtex) || !oqfrags || !oqwater || drawtex == DRAWTEX_MINIMAP) return;
return c;
}
-VAR(dbgvars, 0, 0, 1);
-
void savevslot(stream *f, VSlot &vs, int prev)
{
f->putlil<int>(vs.changed);
if(vslots.empty()) return;
int *prev = new int[numvslots];
for(int i=0;i<numvslots;++i)prev[i]=-1;
- //~memset((void*)prev, -1, (size_t)numvslots*sizeof(int));
loopi(numvslots)
{
VSlot *vs = vslots[i];
int *prev = new (false) int[numvslots];
if(!prev) return;
for(int i=0;i<numvslots;++i)prev[i]=-1;
- //~memset((void*)prev, -1, (size_t)numvslots*sizeof(int));
while(numvslots > 0)
{
int changed = f->getlil<int>();
switch(id.type)
{
case ID_VAR:
- if(dbgvars) conoutf(CON_DEBUG, "wrote var %s: %d", id.name, *id.storage.i);
f->putlil<int>(*id.storage.i);
break;
case ID_FVAR:
- if(dbgvars) conoutf(CON_DEBUG, "wrote fvar %s: %f", id.name, *id.storage.f);
f->putlil<float>(*id.storage.f);
break;
case ID_SVAR:
- if(dbgvars) conoutf(CON_DEBUG, "wrote svar %s: %s", id.name, *id.storage.s);
f->putlil<ushort>(strlen(*id.storage.s));
f->write(*id.storage.s, strlen(*id.storage.s));
break;
}
});
- if(dbgvars) conoutf(CON_DEBUG, "wrote %d vars", hdr.numvars);
-
f->putchar((int)strlen(game::gameident()));
f->write(game::gameident(), (int)strlen(game::gameident())+1);
f->putlil<ushort>(entities::extraentinfosize());
{
int val = f->getlil<int>();
if(exists && id->minval <= id->maxval) setvar(name, val);
- if(dbgvars) conoutf(CON_DEBUG, "read var %s: %d", name, val);
break;
}
{
float val = f->getlil<float>();
if(exists && id->minvalf <= id->maxvalf) setfvar(name, val);
- if(dbgvars) conoutf(CON_DEBUG, "read fvar %s: %f", name, val);
break;
}
val[min(slen, MAXSTRLEN-1)] = '\0';
if(slen >= MAXSTRLEN) f->seek(slen - (MAXSTRLEN-1), SEEK_CUR);
if(exists) setsvar(name, val);
- if(dbgvars) conoutf(CON_DEBUG, "read svar %s: %s", name, val);
break;
}
}
}
- if(dbgvars) conoutf(CON_DEBUG, "read %d vars", hdr.numvars);
string gametype;
copystring(gametype, "fps");
if(weaprange(d, d->gunselect, dist) || (d->skill <= 100 && !rnd(d->skill)))
{
if(d->gunselect == GUN_FIST) return true;
- float skew = clamp(float(lastmillis-d->ai->enemymillis)/float((d->skill*guns[d->gunselect].attackdelay/200.f)), 0.f, guns[d->gunselect].projspeed ? 0.25f : 1e16f),
+ float skew = clamp(float(lastmillis-d->ai->enemymillis)/float((d->skill*guns[d->gunselect].attackdelay/200.f)), 0.f, guns[d->gunselect].projspeed ? 0.25f : 1e16f),
offy = yaw-d->yaw, offp = pitch-d->pitch;
if(offy > 180) offy -= 360;
else if(offy < -180) offy += 360;
}
}
}
- if(cmode) cmode->aifind(d, b, interests);
if(m_teammode) assist(d, b, interests);
return parseinterests(d, b, interests, override);
}
}
}
- bool check(fpsent *d, aistate &b)
- {
- if(cmode && cmode->aicheck(d, b)) return true;
- return false;
- }
-
int dowait(fpsent *d, aistate &b)
{
d->ai->clear(true); // ensure they're clean
- if(check(d, b) || find(d, b)) return 1;
+ if(find(d, b)) return 1;
if(target(d, b, 4, false)) return 1;
if(target(d, b, 4, true)) return 1;
if(randomnode(d, b, SIGHTMIN, 1e16f))
switch(b.targtype)
{
case AI_T_NODE:
- if(check(d, b)) return 1;
if(iswaypoint(b.target)) return defend(d, b, waypoints[b.target].o) ? 1 : 0;
break;
case AI_T_ENTITY:
- if(check(d, b)) return 1;
if(entities::ents.inrange(b.target)) return defend(d, b, entities::ents[b.target]->o) ? 1 : 0;
break;
- case AI_T_AFFINITY:
- if(cmode) return cmode->aidefend(d, b) ? 1 : 0;
- break;
case AI_T_PLAYER:
{
- if(check(d, b)) return 1;
fpsent *e = getclient(b.target);
if(e && e->state == CS_ALIVE) return defend(d, b, e->feetpos()) ? 1 : 0;
break;
switch(b.targtype)
{
case AI_T_NODE: // this is like a wait state without sitting still..
- if(check(d, b) || find(d, b)) return 1;
+ if(find(d, b)) return 1;
if(target(d, b, 4, true)) return 1;
if(iswaypoint(b.target) && vec(waypoints[b.target].o).sub(d->feetpos()).magnitude() > CLOSEDIST)
return makeroute(d, b, waypoints[b.target].o) ? 1 : 0;
{
case AI_T_NODE:
{
- if(check(d, b)) return 1;
if(iswaypoint(b.target))
return defend(d, b, waypoints[b.target].o) ? 1 : 0;
break;
}
- case AI_T_AFFINITY:
- {
- if(cmode) return cmode->aipursue(d, b) ? 1 : 0;
- break;
- }
-
case AI_T_PLAYER:
{
- //if(check(d, b)) return 1;
fpsent *e = getclient(b.target);
if(e && e->state == CS_ALIVE)
{
moveplayer(d, 10, true);
if(allowmove && !b.idle) timeouts(d, b);
if(d->quadmillis) entities::checkquad(curtime, d);
- entities::checkitems(d);
- if(cmode) cmode->checkitems(d);
+ entities::checkitems(d);
}
}
else if(d->state == CS_DEAD)
c.override = false;
cleannext = false;
}
- if(d->state == CS_DEAD && d->respawned!=d->lifesequence && (!cmode || cmode->respawnwait(d, 250) <= 0) && lastmillis - d->lastpain >= 500)
+ if(d->state == CS_DEAD && d->respawned!=d->lifesequence && lastmillis - d->lastpain >= 500)
{
addmsg(N_TRYSPAWN, "rc", d);
d->respawned = d->lifesequence;
}
if(bot)
{
- if(smode && bot->state.state==CS_ALIVE) smode->changeteam(bot, bot->team, t.team);
copystring(bot->team, t.team, MAXTEAMLEN+1);
sendf(-1, 1, "riisi", N_SETTEAM, bot->clientnum, bot->team, 0);
}
{
int cn = ci->clientnum - MAXCLIENTS;
if(!bots.inrange(cn)) return;
- if(ci->ownernum >= 0 && !ci->aireinit && smode) smode->leavegame(ci, true);
sendf(-1, 1, "ri2", N_CDIS, ci->clientnum);
clientinfo *owner = (clientinfo *)getclientinfo(ci->ownernum);
if(owner) owner->bots.removeobj(ci);
void shiftai(clientinfo *ci, clientinfo *owner = NULL)
{
- if(ci->ownernum >= 0 && !ci->aireinit && smode) smode->leavegame(ci, true);
clientinfo *prevowner = (clientinfo *)getclientinfo(ci->ownernum);
if(prevowner) prevowner->bots.removeobj(ci);
if(!owner) { ci->aireinit = 0; ci->ownernum = -1; }
namespace game
{
- clientmode *cmode = NULL;
-
- void setclientmode()
- {
- cmode = NULL;
- }
-
bool senditemstoserver = false, sendcrc = false; // after a map change, since server doesn't have map data
int lastping = 0;
}
if(senditemstoserver)
{
- if(!m_noitems || cmode!=NULL) p.reliable();
+ if(!m_noitems) p.reliable();
if(!m_noitems) entities::putitems(p);
- if(cmode) cmode->senditems(p);
senditemstoserver = false;
}
if(messages.length())
showscores(false);
lasthit = 0;
}
- if(cmode) cmode->respawned(s);
- ai::spawned(s);
+ ai::spawned(s);
addmsg(N_SPAWN, "rcii", s, s->lifesequence, s->gunselect);
break;
}
actor->frags = frags;
if(m_teammode) setteaminfo(actor->team, tfrags);
extern int hidefrags;
- if(actor!=player1 && (!cmode || !cmode->hidefrags() || !hidefrags))
+ if(actor!=player1 && (!hidefrags))
{
defformatstring(ds, "%d", actor->frags);
particle_textcopy(actor->abovehead(), ds, PART_TEXT, 2000, 0x32FF64, 4.0f, -8);
B: 0 EXT_PLAYERSTATS cn #a client number or -1 for all players#
C: 0 EXT_TEAMSCORE
- Server:
+ Server:
--------
A: 0 EXT_UPTIME EXT_ACK EXT_VERSION uptime #in seconds#
B: 0 EXT_PLAYERSTATS cn #send by client# EXT_ACK EXT_VERSION 0 or 1 #error, if cn was > -1 and client does not exist# ...
{
sendstring(team, p);
putint(p, score);
- if(!smode || !smode->extinfoteam(team, p))
- putint(p,-1); //no bases follow
+ putint(p,-1); //no bases follow
}
void extinfoteams(ucharbuf &p)
if(!m_teammode) return;
vector<teamscore> scores;
- if(smode && smode->hidefrags()) smode->getteamscores(scores);
loopv(clients)
{
clientinfo *ci = clients[i];
if(ci->state.state!=CS_SPECTATOR && ci->team[0] && scores.htfind(ci->team) < 0)
{
- if(smode && smode->hidefrags()) scores.add(teamscore(ci->team, 0));
- else { teaminfo *ti = teaminfos.access(ci->team); scores.add(teamscore(ci->team, ti ? ti->frags : 0)); }
+ teaminfo *ti = teaminfos.access(ci->team);
+ scores.add(teamscore(ci->team, ti ? ti->frags : 0));
}
}
loopv(scores) extinfoteamscore(p, scores[i].team, scores[i].score);
void extserverinforeply(ucharbuf &req, ucharbuf &p)
{
- int extcmd = getint(req); // extended commands
+ int extcmd = getint(req); // extended commands
//Build a new packet
putint(p, EXT_ACK); //send ack
case EXT_PLAYERSTATS:
{
int cn = getint(req); //a special player, -1 for all
-
+
clientinfo *ci = NULL;
if(cn >= 0)
{
}
putint(p, EXT_NO_ERROR); //so far no error can happen anymore
-
+
ucharbuf q = p; //remember buffer position
putint(q, EXT_PLAYERSTATS_RESP_IDS); //send player ids following
if(ci) putint(q, ci->clientnum);
else loopv(clients) putint(q, clients[i]->clientnum);
sendserverinforeply(q);
-
+
if(ci) extinfoplayer(p, ci);
else loopv(clients) extinfoplayer(p, clients[i]);
return;
spawnplayer(player1);
showscores(false);
lasthit = 0;
- if(cmode) cmode->respawned(player1);
}
}
moveplayer(player1, 10, true);
swayhudgun(curtime);
entities::checkitems(player1);
- if(cmode) cmode->checkitems(player1);
}
}
if(player1->clientnum>=0) c2sinfo(); // do this last, to reduce the effective frame lag
{
fpsent *p = (fpsent *)d;
vec loc = vec(e.o).addz(p->eyeheight);
- float maxrange = !m_noitems ? 400.0f : (cmode ? 300.0f : 110.0f);
+ float maxrange = !m_noitems ? 400.0f : 110.0f;
float minplayerdist = maxrange;
loopv(players)
{
if(raycube(loc, dir, dist) < dist) dist *= 1.5f;
minplayerdist = min(minplayerdist, dist);
}
- float rating = 1.0f - proximityscore(minplayerdist, 80.0f, maxrange);
- return cmode ? harmonicmean(rating, cmode->ratespawn(p, e)) : rating;
+ return 1.0f - proximityscore(minplayerdist, 80.0f, maxrange);
}
void pickgamespawn(fpsent *d)
{
int ent = d == player1 && respawnent >= 0 ? respawnent : -1;
- int tag = cmode ? cmode->getspawngroup(d) : 0;
- findplayerspawn(d, ent, tag);
+ findplayerspawn(d, ent, 0);
}
void spawnplayer(fpsent *d) // place at random spawn
if(player1->state==CS_DEAD)
{
player1->attacking = false;
- int wait = cmode ? cmode->respawnwait(player1) : 0;
- if(wait>0)
- {
- lastspawnattempt = lastmillis;
- //conoutf(CON_GAMEINFO, "\f2you must wait %d second%s before respawn!", wait, wait!=1 ? "s" : "");
- return;
- }
- if(lastmillis < player1->lastpain + spawnwait) return;
respawnself();
}
}
d->state = CS_DEAD;
d->lastpain = lastmillis;
if(!restore) d->deaths++;
- //~{
- //~gibeffect(max(-d->health, 0), d->vel, d);
- //~d->deaths++;
- //~}
+
if(d==player1)
{
if(deathscore) showscores(true);
disablezoom();
if(!restore) loopi(NUMGUNS) savedammo[i] = player1->ammo[i];
d->attacking = false;
- //d->pitch = 0;
d->roll = 0;
playsound(S_DIE1+rnd(2));
}
}
else if((d->state!=CS_ALIVE && d->state != CS_LAGGED && d->state != CS_SPAWNING) || intermission) return;
- if(cmode) cmode->died(d, actor);
-
fpsent *h = followingplayer(player1);
int contype = d==h || actor==h ? CON_FRAG_SELF : CON_FRAG_OTHER;
const char *dname = "", *aname = "";
{
intermission = true;
player1->attacking = false;
- if(cmode) cmode->gameover();
conoutf(CON_GAMEINFO, "\f2intermission:");
conoutf(CON_GAMEINFO, "\f2game has ended!");
conoutf(CON_GAMEINFO, "\f2player frags: %d, deaths: %d", player1->frags, player1->deaths);
removeweapons(d);
removetrackedparticles(d);
removetrackeddynlights(d);
- if(cmode) cmode->removeplayer(d);
players.removeobj(d);
DELETEP(clients[cn]);
cleardynentcache();
d->respawned = d->suicided = -2;
}
- setclientmode();
-
intermission = false;
maptime = maprealtime = 0;
maplimit = -1;
- if(cmode)
- {
- cmode->preload();
- cmode->setup();
- }
-
conoutf(CON_GAMEINFO, "\f2game mode is %s", server::modename(gamemode));
const char *info = m_valid(gamemode) ? gamemodes[gamemode - STARTGAMEMODE].info : NULL;
pophudmatrix();
}
- //~void drawspeedometer(fpsent *d, int w, int h) {
- //~int speedforreal = (int) (sqrtf(d->vel.squaredlen()) + 1.0f);
- //~speedforreal = (speedforreal == 1) ? 0 : speedforreal;
- //~vec colour = vec(255, 255, 255);
- //~float realw = 0;
- //~float realh = 0;
- //~if (speedometercolor) {
- //~if (speedforreal==0) colour = vec(60, 60, 60);
- //~else if (speedforreal>0 && speedforreal<=60) colour = vec(240, 30, 30);
- //~else if (speedforreal>60 && speedforreal<=120) colour = vec(180, 90, 60);
- //~else if (speedforreal>120 && speedforreal<=180) colour = vec(180, 180, 30);
- //~else if (speedforreal>180 && speedforreal<=240) colour = vec(90, 180, 60);
- //~else colour = vec(30, 240, 30);
- //~}
-
- //~defformatstring(speedstring, "%d", speedforreal);
- //~text_boundsf(speedstring, realw, realh);
- //~vec2 offset = vec2(speedometerx, speedometery).mul(vec2(w, h).div(speedometerscale));
- //~offset.x -= realw/2.0f;
- //~offset.y -= realh/2.0f;
-
- //~pushhudmatrix();
- //~hudmatrix.scale(speedometerscale, speedometerscale, 1);
- //~flushhudmatrix();
-
- //~draw_text(speedstring, int(offset.x), int(offset.y), colour.x, colour.y, colour.z, speedometeralpha);
-
- //~pophudmatrix();
- //~}
-
void hudquad(float x, float y, float w, float h, float r = 1, float g = 1, float b = 1, float tx = 0, float ty = 0, float tw = 1, float th = 1)
{
gle::defvertex(2);
gle::deftexcoord0();
gle::colorf(r, g, b);
gle::begin(GL_TRIANGLE_STRIP);
- //~gle::begin(GL_QUADS);
gle::attribf(x, y); gle::attribf(tx, ty);
gle::attribf(x+w, y); gle::attribf(tx + tw, ty);
gle::attribf(x, y+h); gle::attribf(tx, ty + th);
void drawhudicons(fpsent *d, int w, int h)
{
- //~defformatstring(health, "%d", d->state==CS_DEAD ? 0 : d->health);
- //~bvec healthcolor = bvec::hexcolor(healthcolors && !m_insta ? (d->state==CS_DEAD ? 0x808080 : (d->health<=25 ? 0xFF0000 : (d->health<=50 ? 0xFF8000 : (d->health<=100 ? 0xFFFFFF : 0x40C0FF)))) : 0xFFFFFF);
- //~draw_text(health, (HICON_X + HICON_SIZE + HICON_SPACE)/2, HICON_TEXTY/2, healthcolor.r, healthcolor.g, healthcolor.b);
- //~if(d->state!=CS_DEAD)
- //~{
- //~if(d->armour) draw_textf("%d", (HICON_X + HICON_STEP + HICON_SIZE + HICON_SPACE)/2, HICON_TEXTY/2, d->armour);
- //~draw_textf("%d", (HICON_X + 2*HICON_STEP + HICON_SIZE + HICON_SPACE)/2, HICON_TEXTY/2, d->ammo[d->gunselect]);
- //~}
-
- //~if(d->state != CS_DEAD && d->maxhealth > 100)
- //~{
- //~float scale = 0.66f;
- //~pushhudmatrix();
- //~hudmatrix.scale(scale, scale, 1);
- //~flushhudmatrix();
-
- //~float width, height;
- //~text_boundsf(health, width, height);
- //~draw_textf("/%d", (HICON_X + HICON_SIZE + HICON_SPACE + width*2)/scale, (HICON_TEXTY + height)/scale, d->maxhealth);
-
- //~pophudmatrix();
- //~}
-
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
float ammoratio = (float)p->ammo[gun] / itemstats[gun-GUN_SG].add;
bvec color = bvec::hexcolor(p->ammo[gun] == 0 || ammoratio >= 1.0f ? 0xFFFFFF : (ammoratio >= 0.5f ? 0xFFC040 : 0xFF0000));
draw_text(label, textdrawpos.x, textdrawpos.y, color.r, color.g, color.b, alpha);
- /// ALIGN STUFF AND ADD COMMAND FOR IT...
- //~text_bounds(label, movew, moveh);
- //~moved = movew + 6;
- //~defformatstring(damagedealt, "| %d ", pwdamagedealt[gun]);
- //~draw_text(damagedealt, textdrawpos.x+moved, textdrawpos.y, color.r, color.g, color.b, alpha);
- //~text_bounds(damagedealt, movew, moveh);
- //~moved += movew;
- //~defformatstring(accuracy, "| %d %%", pwaccuracy[gun]);
- //~draw_text(accuracy, textdrawpos.x+moved, textdrawpos.y, color.r, color.g, color.b, alpha);
pophudmatrix();
}
pophudmatrix();
}
- //~void newhud(int w, int h) //new SauerEnhanced HUD
- //~{
- //~if(player1->state==CS_DEAD || player1->state==CS_SPECTATOR) return;
- //~glPushMatrix();
- //~glScalef(1/1.2f, 1/1.2f, 1);
- //~pushhudmatrix();
- //~hudmatrix.scale(w/1800.0f, h/1650.0f, 1);
- //~hudmatrix.scale(1.0f/1.2f, 1.0f/1.2f, 1);
- //~flushhudmatrix();
- //~if(!m_insta) draw_textf("%d", 80, h*1.2f-128, player1->state==CS_DEAD ? 0 : player1->health);
- //~defformatstring(ammo, "%d", player1->ammo[player1->gunselect]);
- //~int wb, hb;
- //~text_bounds(ammo, wb, hb);
- //~draw_textf("%d", w*1.2f-wb-80, h*1.2f-128, player1->ammo[player1->gunselect]);
-
- //~hudmatrix.ortho(0, w, h, 0, -1, 1);
- //~resethudmatrix();
-
- //~hudshader->set();
- //~gle::colorf(1, 1, 1);
-
- //~gle::defvertex(2);
- //~gle::deftexcoord0();
-
- //~if(player1->quadmillis)
- //~{
- //~gle::begin(GL_QUADS);
- //~loopj(numdecals)
- //~{
- //~float hsz = decals[j].size, hx = clamp(decals[j].x, hsz, w-hsz), hy = clamp(decals[j].y, hsz, h-hsz), side = decals[j].side;
- //~gle::attribf(hx-hsz, hy-hsz); gle::attribf(side, 0);
- //~gle::attribf(hx+hsz, hy-hsz); gle::attribf(1-side, 0);
- //~gle::attribf(hx+hsz, hy+hsz); gle::attribf(1-side, 1);
- //~gle::attribf(hx-hsz, hy+hsz); gle::attribf(side, 1);
- //~}
- //~gle::end();
- //~settexture("packages/hud/hud_quaddamage_left.png"); //QuadDamage left glow
- //~gle::begin(GL_QUADS);
- //~gle::attribf(0, h*1.2f-207); gle::attribf(0.0f, 0.0f);
- //~gle::attribf(539, h*1.2f-207); gle::attribf(1.0f, 0.0f);
- //~gle::attribf(539, h*1.2f); gle::attribf(1.0f, 1.0f);
- //~gle::attribf(0, h*1.2f); gle::attribf(0.0f, 1.0f);
- //~gle::end();
-
- //~settexture("packages/hud/hud_quaddamage_right.png"); //QuadDamage right glow
- //~gle::begin(GL_QUADS);
- //~gle::attribf(w*1.2f-135, h*1.2f-207); gle::attribf(0.0f, 0.0f);
- //~gle::attribf(w*1.2f, h*1.2f-207); gle::attribf(1.0f, 0.0f);
- //~gle::attribf(w*1.2f, h*1.2f); gle::attribf(1.0f, 1.0f);
- //~gle::attribf(w*1.2f-135, h*1.2f); gle::attribf(0.0f, 1.0f);
- //~gle::end();
- //~}
-
- //~if(player1->maxhealth > 100)
- //~{
- //~settexture("packages/hud/hud_megahealth.png"); //HealthBoost indicator
- //~gle::begin(GL_QUADS);
- //~gle::attribf(0, h*1.2f-207); gle::attribf(0.0f, 0.0f);
- //~gle::attribf(539, h*1.2f-207); gle::attribf(1.0f, 0.0f);
- //~gle::attribf(539, h*1.2f); gle::attribf(1.0f, 1.0f);
- //~gle::attribf(0, h*1.2f); gle::attribf(0.0f, 1.0f);
- //~gle::end();
- //~}
-
- //~gle::begin(GL_QUADS);
- //~gle::attribf(w/2-speedow/2, h/2-speedoh/2); gle::attribf(0.0f, 1.0f);
- //~gle::attribf(w/2, h/2-speedoh/2); gle::attribf(1.0f, 1.0f);
- //~gle::attribf(w/2, h/2); gle::attribf(1.0f, 1.0f);
- //~gle::attribf(w/2-speedow/2, h/2); gle::attribf(0.0f, 1.0f);
- //~gle::end();
-
- //~int health = (player1->health*100)/player1->maxhealth,
- //~armour = (player1->armour*100)/200,
- //~hh = (health*101)/100;
-
- //~float hs = (health*1.0f)/100;
-
- //~if(player1->health > 0 && !m_insta)
- //~{
- //~settexture("packages/hud/hud_health.png"); //Health bar
- //~hudquad(4000, 600, 97, 56);
- //~gle::begin(GL_QUADS);
- //~gle::attribf(47, h*1.2f-hh-56); gle::attribf(0.0f, 1.0f-hs);
- //~gle::attribf(97, h*1.2f-hh-56); gle::attribf(1.0f, 1.0f-hs);
- //~gle::attribf(97, h*1.2f-57); gle::attribf(1.0f, 1.0f);
- //~gle::attribf(47, h*1.2f-57); gle::attribf(0.0f, 1.0f);
- //~gle::end();
- //~}
-
- //~if(player1->armour > 0)
- //~{
- //~settexture("packages/hud/hud_armour.png"); //Armour bar
- //~gle::begin(GL_QUADS);
- //~gle::attribf(130, h*1.2f-62);gle::attribf(0.0f, 0.0f);
- //~gle::attribf(130+ah, h*1.2f-62);gle::attribf(as, 0.0f);
- //~gle::attribf(130+ah, h*1.2f-44);gle::attribf(as, 1.0f);
- //~gle::attribf(130, h*1.2f-44);gle::attribf(0.0f, 1.0f);
- //~gle::end();
- //~}
-
- //~if(!m_insta)
- //~{
- //~settexture("packages/hud/hud_left.png"); //left HUD
- //~gle::begin(GL_QUADS);
- //~gle::attribf(0, h*1.2f-207);gle::attribf(0.0f, 0.0f);
- //~gle::attribf(539, h*1.2f-207);gle::attribf(1.0f, 0.0f);
- //~gle::attribf(539, h*1.2f );gle::attribf(1.0f, 1.0f);
- //~gle::attribf(0, h*1.2f );gle::attribf(0.0f, 1.0f);
- //~gle::end();
- //~}
-
- //~settexture("packages/hud/hud_right.png"); //right HUD
- //~gle::begin(GL_QUADS);
- //~gle::attribf(w*1.2f-135, h*1.2f-207);gle::attribf(0.0f, 0.0f);
- //~gle::attribf(w*1.2f, h*1.2f-207);gle::attribf(1.0f, 0.0f);
- //~gle::attribf(w*1.2f, h*1.2f );gle::attribf(1.0f, 1.0f);
- //~gle::attribf(w*1.2f-135, h*1.2f );gle::attribf(0.0f, 1.0f);
- //~gle::end();
-
- //~int maxammo = 0;
-
- //~switch(player1->gunselect)
- //~{
- //~case GUN_FIST:
- //~maxammo = 1;
- //~break;
-
- //~case GUN_RL:
- //~case GUN_RIFLE:
- //~maxammo = m_insta ? 100 : 15;
- //~break;
-
- //~case GUN_SG:
- //~case GUN_GL:
- //~maxammo = 30;
- //~break;
-
- //~case GUN_CG:
- //~maxammo = 60;
- //~break;
-
- //~case GUN_PISTOL:
- //~maxammo = 120;
- //~break;
- //~}
-
- //~int curammo = (player1->ammo[player1->gunselect]*100)/maxammo,
- //~amh = (curammo*101)/100;
-
- //~float ams = (curammo*1.0f)/100;
-
- //~if(player1->ammo[player1->gunselect] > 0)
- //~{
- //~settexture("packages/hud/hud_health.png"); //Ammo bar
- //~gle::begin(GL_QUADS);
- //~gle::attribf(w*1.2f-47, h*1.2f-amh-56);gle::attribf(0.0f, 1.0f-ams);
- //~gle::attribf(w*1.2f-97, h*1.2f-amh-56);gle::attribf(1.0f, 1.0f-ams);
- //~gle::attribf(w*1.2f-97, h*1.2f-57 );gle::attribf(1.0f, 1.0f);
- //~gle::attribf(w*1.2f-47, h*1.2f-57 );gle::attribf(0.0f, 1.0f);
- //~gle::end();
- //~}
- //~glPopMatrix();
- //~pophudmatrix();
- //~}
-
void gameplayhud(int w, int h)
{
- //~newhud(w, h);
-
pushhudmatrix();
hudmatrix.scale(h/1800.0f, h/1800.0f, 1);
flushhudmatrix();
}
fpsent *d = hudplayer();
- if(d->state!=CS_EDITING)
- {
- if(cmode) cmode->drawhud(d, w, h);
- }
pophudmatrix();
int clipconsole(int w, int h)
{
- if(cmode) return cmode->clipconsole(w, h);
return 0;
}
namespace game
{
- struct clientmode
- {
- virtual ~clientmode() {}
-
- virtual void preload() {}
- virtual int clipconsole(int w, int h) { return 0; }
- virtual void drawhud(fpsent *d, int w, int h) {}
- virtual void rendergame() {}
- virtual void respawned(fpsent *d) {}
- virtual void setup() {}
- virtual void checkitems(fpsent *d) {}
- virtual int respawnwait(fpsent *d, int delay = 0) { return 0; }
- virtual int getspawngroup(fpsent *d) { return 0; }
- virtual float ratespawn(fpsent *d, const extentity &e) { return 1.0f; }
- virtual void senditems(packetbuf &p) {}
- virtual void removeplayer(fpsent *d) {}
- virtual void died(fpsent *victim, fpsent *actor) {}
- virtual void gameover() {}
- virtual bool hidefrags() { return false; }
- virtual int getteamscore(const char *team) { return 0; }
- virtual void getteamscores(vector<teamscore> &scores) {}
- virtual void aifind(fpsent *d, ai::aistate &b, vector<ai::interest> &interests) {}
- virtual bool aicheck(fpsent *d, ai::aistate &b) { return false; }
- virtual bool aidefend(fpsent *d, ai::aistate &b) { return false; }
- virtual bool aipursue(fpsent *d, ai::aistate &b) { return false; }
- };
-
- extern clientmode *cmode;
- extern void setclientmode();
-
// fps
extern int gamemode, nextmode;
extern string clientmap;
extern void explode(bool local, fpsent *owner, const vec &v, dynent *safe, int dam, int gun);
extern void explodeeffects(int gun, fpsent *d, bool local, int id = 0);
extern void damageeffect(int damage, fpsent *d, bool thirdperson = true);
- //~extern void gibeffect(int damage, const vec &vel, fpsent *d);
extern float intersectdist;
extern bool intersect(dynent *d, const vec &from, const vec &to, float &dist = intersectdist);
extern dynent *intersectclosest(const vec &from, const vec &to, fpsent *at, float &dist = intersectdist);
entities::renderentities();
renderbouncers();
renderprojectiles();
- if(cmode) cmode->rendergame();
-
-#if 0
- if(dbgspawns) renderspawns();
-#endif
endmodelbatches();
}
void getbestteams(vector<const char *> &best)
{
- if(cmode && cmode->hidefrags())
+ if(!hidefrags)
{
vector<teamscore> teamscores;
- cmode->getteamscores(teamscores);
teamscores.sort(teamscore::compare);
while(teamscores.length() > 1 && teamscores.last().score < teamscores[0].score) teamscores.drop();
loopv(teamscores) best.add(teamscores[i].team);
scoregroup &g = *groups[numgroups++];
g.team = team;
if(!team) g.score = 0;
- else if(cmode && cmode->hidefrags()) g.score = cmode->getteamscore(o->team);
else { teaminfo *ti = teaminfos.access(team); g.score = ti ? ti->frags : 0; }
g.players.setsize(0);
g.players.add(o);
g.pushlist(); // horizontal
}
- if(!cmode || !cmode->hidefrags() || !hidefrags)
+ if(!hidefrags)
{
g.pushlist();
g.strut(6);
return cname[cidx];
}
- struct servmode
- {
- virtual ~servmode() {}
-
- virtual void entergame(clientinfo *ci) {}
- virtual void leavegame(clientinfo *ci, bool disconnecting = false) {}
-
- virtual void moved(clientinfo *ci, const vec &oldpos, bool oldclip, const vec &newpos, bool newclip) {}
- virtual bool canspawn(clientinfo *ci, bool connecting = false) { return true; }
- virtual void spawned(clientinfo *ci) {}
- virtual int fragvalue(clientinfo *victim, clientinfo *actor)
- {
- if(victim==actor || isteam(victim->team, actor->team)) return -1;
- return 1;
- }
- virtual void died(clientinfo *victim, clientinfo *actor) {}
- virtual bool canchangeteam(clientinfo *ci, const char *oldteam, const char *newteam) { return true; }
- virtual void changeteam(clientinfo *ci, const char *oldteam, const char *newteam) {}
- virtual void initclient(clientinfo *ci, packetbuf &p, bool connecting) {}
- virtual void update() {}
- virtual void cleanup() {}
- virtual void setup() {}
- virtual void newmap() {}
- virtual void intermission() {}
- virtual bool hidefrags() { return false; }
- virtual int getteamscore(const char *team) { return 0; }
- virtual void getteamscores(vector<teamscore> &scores) {}
- virtual bool extinfoteam(const char *team, ucharbuf &p) { return false; }
- };
-
- #define SERVMODE 1
- servmode *smode = NULL;
-
bool canspawnitem(int type) { return !m_noitems && (type>=I_SHELLS && type<=I_QUAD && (!m_noammo || type<I_SHELLS || type>I_CARTRIDGES)); }
int spawntime(int type)
float rank;
clientinfo *ci = choosebestclient(rank);
if(!ci) break;
- if(smode && smode->hidefrags()) rank = 1;
- else if(selected && rank<=0) break;
+ if(selected && rank<=0) break;
ci->state.timeplayed = -1;
team[first].add(ci);
if(rank>0) teamrank[first] += rank;
{
clientinfo *ci = team[i][j];
if(!strcmp(ci->team, teamnames[i])) continue;
- if(persistteams && ci->team[0] && (!smode || smode->canchangeteam(ci, teamnames[i], ci->team)))
+ if(persistteams && ci->team[0])
{
addteaminfo(ci->team);
continue;
loopi(numteams-1)
{
teamrank &ts = teamranks[i];
- if(smode && smode->hidefrags())
- {
- if(ts.clients < worst->clients || (ts.clients == worst->clients && ts.rank < worst->rank)) worst = &ts;
- }
- else if(ts.rank < worst->rank || (ts.rank == worst->rank && ts.clients < worst->clients)) worst = &ts;
+ if(ts.rank < worst->rank || (ts.rank == worst->rank && ts.clients < worst->clients)) worst = &ts;
}
return worst->name;
}
}
if(ci && (m_demo || m_mp(gamemode)) && ci->state.state!=CS_SPECTATOR)
{
- if(smode && !smode->canspawn(ci, true))
- {
- ci->state.state = CS_DEAD;
- putint(p, N_FORCEDEATH);
- putint(p, ci->clientnum);
- sendf(-1, 1, "ri2x", N_FORCEDEATH, ci->clientnum, ci->clientnum);
- }
- else
- {
- gamestate &gs = ci->state;
- spawnstate(ci);
- putint(p, N_SPAWNSTATE);
- putint(p, ci->clientnum);
- sendstate(gs, p);
- gs.lastspawn = gamemillis;
- }
+ gamestate &gs = ci->state;
+ spawnstate(ci);
+ putint(p, N_SPAWNSTATE);
+ putint(p, ci->clientnum);
+ sendstate(gs, p);
+ gs.lastspawn = gamemillis;
}
if(ci && ci->state.state==CS_SPECTATOR)
{
putint(p, -1);
welcomeinitclient(p, ci ? ci->clientnum : -1);
}
- if(smode) smode->initclient(ci, p, true);
return 1;
}
stopdemo();
pausegame(false);
changegamespeed(100);
- if(smode) smode->cleanup();
aiman::clearai();
gamemode = mode;
sendf(-1, 1, "risii", N_MAPCHANGE, smapname, gamemode, 1);
- smode = NULL;
-
clearteaminfo();
if(m_teammode) autoteam();
if(demonextmatch) setupdemorecord();
demonextmatch = autorecorddemo!=0;
}
-
- if(smode) smode->setup();
}
void rotatemap(bool next)
if(m_teammode)
{
vector<teamscore> scores;
- if(smode && smode->hidefrags()) smode->getteamscores(scores);
loopv(clients)
{
clientinfo *ci = clients[i];
if(ci->state.state==CS_SPECTATOR || !ci->team[0]) continue;
int score = 0;
- if(smode && smode->hidefrags())
- {
- int idx = scores.htfind(ci->team);
- if(idx >= 0) score = scores[idx].score;
- }
- else if(teaminfo *ti = teaminfos.access(ci->team)) score = ti->frags;
+ if(teaminfo *ti = teaminfos.access(ci->team)) score = ti->frags;
if(!topteam || score > topscore) { topteam = ci->team; topscore = score; tied = false; }
else if(score == topscore && strcmp(ci->team, topteam)) tied = true;
}
if(gamemillis >= gamelimit && !interm && (force || !checkovertime()))
{
sendf(-1, 1, "ri2", N_TIMEUP, 0);
- if(smode) smode->intermission();
changegamespeed(100);
interm = gamemillis + 10000;
}
if(ts.health<=0)
{
target->state.deaths++;
- int fragvalue = smode ? smode->fragvalue(target, actor) : (target==actor || isteam(target->team, actor->team) ? -1 : 1);
+ int fragvalue = (target==actor || isteam(target->team, actor->team) ? -1 : 1);
actor->state.frags += fragvalue;
if(fragvalue>0)
{
if(t) t->frags += fragvalue;
sendf(-1, 1, "ri5", N_DIED, target->clientnum, actor->clientnum, actor->state.frags, t ? t->frags : 0);
target->position.setsize(0);
- if(smode) smode->died(target, actor);
ts.state = CS_DEAD;
ts.lastdeath = gamemillis;
if(actor!=target && isteam(actor->team, target->team))
{
gamestate &gs = ci->state;
if(gs.state!=CS_ALIVE) return;
- int fragvalue = smode ? smode->fragvalue(ci, ci) : -1;
+ int fragvalue = -1;
ci->state.frags += fragvalue;
ci->state.deaths++;
teaminfo *t = m_teammode ? teaminfos.access(ci->team) : NULL;
if(t) t->frags += fragvalue;
sendf(-1, 1, "ri5", N_DIED, ci->clientnum, ci->clientnum, gs.frags, t ? t->frags : 0);
ci->position.setsize(0);
- if(smode) smode->died(ci, NULL);
gs.state = CS_DEAD;
gs.lastdeath = gamemillis;
gs.respawn();
}
}
aiman::checkai();
- if(smode) smode->update();
}
}
void forcespectator(clientinfo *ci)
{
if(ci->state.state==CS_ALIVE) suicide(ci);
- if(smode) smode->leavegame(ci);
ci->state.state = CS_SPECTATOR;
ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed;
if(!ci->local && (!ci->privilege || ci->warned)) aiman::removeai(ci);
clientdisconnect(n);
}
- int clientconnect(int n, uint ip)
+ int clientconnect(int n)
{
clientinfo *ci = getinfo(n);
ci->clientnum = ci->ownernum = n;
if(ci->connected)
{
if(ci->privilege) setmaster(ci, false);
- if(smode) smode->leavegame(ci, true);
ci->state.timeplayed += lastmillis - ci->state.lasttimeplayed;
savescore(ci);
sendf(-1, 1, "ri2", N_CDIS, n);
cp->position.setsize(0);
while(curmsg<p.length()) cp->position.add(p.buf[curmsg++]);
}
- if(smode && cp->state.state==CS_ALIVE) smode->moved(cp, cp->state.o, cp->gameclip, pos, (flags&0x80)!=0);
cp->state.o = pos;
cp->gameclip = (flags&0x80)!=0;
}
int val = getint(p);
if(!ci->local && !m_edit) break;
if(val ? ci->state.state!=CS_ALIVE && ci->state.state!=CS_DEAD : ci->state.state!=CS_EDITING) break;
- if(smode)
- {
- if(val) smode->leavegame(ci);
- else smode->entergame(ci);
- }
if(val)
{
ci->state.editstate = ci->state.state;
break;
case N_TRYSPAWN:
- if(!ci || !cq || cq->state.state!=CS_DEAD || cq->state.lastspawn>=0 || (smode && !smode->canspawn(cq))) break;
+ if(!ci || !cq || cq->state.state!=CS_DEAD || cq->state.lastspawn>=0) break;
if(!ci->clientmap[0] && !ci->mapcrc)
{
ci->mapcrc = -1;
cq->state.state = CS_ALIVE;
cq->state.gunselect = gunselect >= GUN_FIST && gunselect <= GUN_PISTOL ? gunselect : GUN_FIST;
cq->exceeded = 0;
- if(smode) smode->spawned(cq);
QUEUE_AI;
QUEUE_BUF({
putint(cm->messages, N_SPAWN);
{
getstring(text, p);
filtertext(text, text, false, false, MAXTEAMLEN);
- if(m_teammode && text[0] && strcmp(ci->team, text) && (!smode || smode->canchangeteam(ci, ci->team, text)) && addteaminfo(text))
+ if(m_teammode && text[0] && strcmp(ci->team, text) && addteaminfo(text))
{
if(ci->state.state==CS_ALIVE) suicide(ci);
copystring(ci->team, text);
if(!ci->privilege && !ci->local) break;
clientinfo *wi = getinfo(who);
if(!m_teammode || !text[0] || !wi || !wi->connected || !strcmp(wi->team, text)) break;
- if((!smode || smode->canchangeteam(wi, wi->team, text)) && addteaminfo(text))
+ if(addteaminfo(text))
{
if(wi->state.state==CS_ALIVE) suicide(wi);
copystring(wi->team, text, MAXTEAMLEN+1);
smapname[0] = '\0';
resetitems();
notgotitems = false;
- if(smode) smode->newmap();
}
QUEUE_MSG;
break;
sendserverinforeply(p);
}
- bool servercompatible(char *name, char *sdec, char *map, int ping, const vector<int> &attr, int np)
- {
- return attr.length() && attr[0]==PROTOCOL_VERSION;
- }
-
#include "aiman.h"
}
};
vector<hitmsg> hits;
- //~VARP(maxdebris, 10, 25, 1000);
-
ICOMMAND(getweapon, "", (), intret(player1->gunselect));
void gunselect(int gun, fpsent *d)
loopi(guns[gun].rays) offsetray(from, to, guns[gun].spread, guns[gun].range, rays[i]);
}
- //~enum { BNC_GRENADE, BNC_GIBS, BNC_DEBRIS };
enum { BNC_GRENADE };
struct bouncer : physent
{
bouncer &bnc = *bouncers.add(new bouncer);
bnc.o = from;
- //~bnc.radius = bnc.xradius = bnc.yradius = type==BNC_DEBRIS ? 0.5f : 1.5f;
bnc.radius = bnc.xradius = bnc.yradius = 1.5f;
bnc.eyeheight = bnc.radius;
bnc.aboveeye = bnc.radius;
bnc.collidetype = COLLIDE_ELLIPSE_PRECISE;
- //~switch(type)
- //~{
- //~case BNC_GRENADE: bnc.collidetype = COLLIDE_ELLIPSE_PRECISE; break;
- //~case BNC_DEBRIS: bnc.variant = rnd(4); break;
- //~case BNC_GIBS: bnc.variant = rnd(3); break;
- //~}
-
vec dir(to);
dir.sub(from).safenormalize();
bnc.vel = dir;
{
if(d->type != ENT_BOUNCE) return;
bouncer *b = (bouncer *)d;
- //~if(b->bouncetype != BNC_GIBS || b->bounces >= 2) return;
if(b->bounces >= 2) return;
b->bounces++;
adddecal(DECAL_BLOOD, vec(b->o).sub(vec(surface).mul(b->radius)), surface, 2.96f/b->bounces, bvec(0x60, 0xFF, 0xFF), rnd(4));
vec old(bnc.o);
bool stopped = false;
if(bnc.bouncetype==BNC_GRENADE) stopped = bounce(&bnc, 0.6f, 0.5f, 0.8f) || (bnc.lifetime -= time)<0;
- //~else
- //~{
- //~// cheaper variable rate physics for debris, gibs, etc.
- //~for(int rtime = time; rtime > 0;)
- //~{
- //~int qtime = min(30, rtime);
- //~rtime -= qtime;
- //~if((bnc.lifetime -= qtime)<0 || bounce(&bnc, qtime/1000.0f, 0.6f, 0.5f, 1)) { stopped = true; break; }
- //~}
- //~}
+
if(stopped)
{
if(bnc.bouncetype==BNC_GRENADE)
newbouncer(p, to, true, 0, d, type, rnd(1000)+1000, rnd(100)+20, light);
}
- //~void gibeffect(int damage, const vec &vel, fpsent *d)
- //~{
- //~if(!blood || damage <= 0) return;
- //~vec from = d->abovehead();
- //~loopi(min(damage/25, 40)+1) spawnbouncer(from, vel, d, BNC_GIBS);
- //~}
-
void hit(int damage, dynent *d, fpsent *at, const vec &vel, int gun, float info1, int info2 = 1)
{
if(at==player1 && d!=at)
if(gun==GUN_RL) adddynlight(v, 1.15f*guns[gun].exprad, vec(2, 1.5f, 1), 700, 100, 0, guns[gun].exprad/2, vec(1, 0.75f, 0.5f));
else if(gun==GUN_GL) adddynlight(v, 1.15f*guns[gun].exprad, vec(0.5f, 1.5f, 2), 600, 100, 0, 8, vec(0.25f, 1, 1));
else adddynlight(v, 1.15f*guns[gun].exprad, vec(2, 1.5f, 1), 700, 100);
- //~int numdebris = rnd(maxdebris-5)+5;
- //~vec debrisvel = vec(owner->o).sub(v).safenormalize(), debrisorigin(v);
- //~if(gun==GUN_RL) debrisorigin.add(vec(debrisvel).mul(8));
- //~if(numdebris)
- //~{
- //~entitylight light;
- //~lightreaching(debrisorigin, light.color, light.dir);
- //~loopi(numdebris)
- //~spawnbouncer(debrisorigin, debrisvel, owner, BNC_DEBRIS, &light);
- //~}
if(!local) return;
int numdyn = numdynents();
loopi(numdyn)
{
case GUN_FIST:
if(d->type==ENT_PLAYER && chainsawhudgun) sound = S_CHAINSAW_ATTACK;
- //~if(d->quadmillis)
- //~particle_splash(PART_FLAME, 60, 300, vec(0).sub(from), 0x802010, 0.24f);
break;
case GUN_SG:
}
static const char * const projnames[2] = { "projectiles/grenade", "projectiles/rocket" };
- //~static const char * const gibnames[3] = { "gibs/gib01", "gibs/gib02", "gibs/gib03" };
- //~static const char * const debrisnames[4] = { "debris/debris01", "debris/debris02", "debris/debris03", "debris/debris04" };
- void preloadbouncers()
- {
+ void preloadbouncers() {
loopi(sizeof(projnames)/sizeof(projnames[0])) preloadmodel(projnames[i]);
- //~loopi(sizeof(gibnames)/sizeof(gibnames[0])) preloadmodel(gibnames[i]);
- //~loopi(sizeof(debrisnames)/sizeof(debrisnames[0])) preloadmodel(debrisnames[i]);
}
void renderbouncers()
int cull = MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED;
float fade = 1;
if(bnc.lifetime < 250) fade = bnc.lifetime/250.0f;
- //~switch(bnc.bouncetype)
- //~{
- //~case BNC_GIBS: mdl = gibnames[bnc.variant]; cull |= MDL_LIGHT|MDL_LIGHT_FAST|MDL_DYNSHADOW; break;
- //~case BNC_DEBRIS: mdl = debrisnames[bnc.variant]; break;
- //~default: continue;
- //~}
rendermodel(&bnc.light, mdl, ANIM_MAPMODEL|ANIM_LOOP, pos, yaw, pitch, cull, NULL, NULL, 0, 0, fade);
}
}
void cleanup();
};
-
+
struct identstack
{
identval val;
};
};
identfun fun; // ID_VAR, ID_FVAR, ID_SVAR, ID_COMMAND
-
+
ident() {}
// ID_VAR
ident(int t, const char *n, int m, int x, int *s, void *f = NULL, int flags = 0)
valtype = v.type;
val = v;
}
-
+
void setval(const identstack &v)
{
valtype = v.valtype;
val = v.val;
}
-
+
void forcenull()
{
if(valtype==VAL_STR) delete[] val.s;
static inline void intformat(char *buf, int v, int len = 20) { nformatstring(buf, len, "%d", v); }
static inline void floatformat(char *buf, float v, int len = 20) { nformatstring(buf, len, v==int(v) ? "%.1f" : "%.6g", v); }
-static inline const char *getstr(const identval &v, int type)
+static inline const char *getstr(const identval &v, int type)
{
switch(type)
{
{
case VAL_INT: return v.i;
case VAL_FLOAT: return int(v.f);
- case VAL_STR: case VAL_MACRO: return parseint(v.s);
+ case VAL_STR: case VAL_MACRO: return parseint(v.s);
default: return 0;
}
}
}
}
inline float tagval::getfloat() const { return ::getfloat(*this, type); }
-inline float ident::getfloat() const { return ::getfloat(val, valtype); }
+inline float ident::getfloat() const { return ::getfloat(val, valtype); }
inline void ident::getval(tagval &v) const
{
#define ICOMMAND(name, nargs, proto, b) ICOMMANDN(name, ICOMMANDNAME(name), nargs, proto, b)
#define ICOMMANDSNAME _icmds_
#define ICOMMANDS(name, nargs, proto, b) ICOMMANDNS(name, ICOMMANDSNAME, nargs, proto, b)
-
+
#define GL_TEXTURE_SWIZZLE_A 0x8E45
#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
#endif
-
static inline bool insideworld(const vec &o)
{
- extern int worldsize;
+ extern int worldsize;
return o.x>=0 && o.x<worldsize && o.y>=0 && o.y<worldsize && o.z>=0 && o.z<worldsize;
}
static inline bool insideworld(const ivec &o)
{
- extern int worldsize;
+ extern int worldsize;
return uint(o.x)<uint(worldsize) && uint(o.y)<uint(worldsize) && uint(o.z)<uint(worldsize);
}
virtual void poplist() {}
virtual bool allowautotab(bool on) = 0;
- virtual bool shouldtab() { return false; }
- virtual void tab(const char *name = NULL, int color = 0) = 0;
+ virtual bool shouldtab() = 0;
+ virtual void tab(const char *name = NULL, int color = 0) = 0;
virtual int image(Texture *t, float scale, const char *overlaid = NULL) = 0;
virtual int texture(VSlot &vslot, float scale, bool overlaid = true) = 0;
- virtual int playerpreview(int model, int team, int weap, float scale, const char *overlaid = NULL) { return 0; }
- virtual int modelpreview(const char *name, int anim, float scale, const char *overlaid = NULL, bool throttle = false) { return 0; }
- virtual int prefabpreview(const char *prefab, const vec &color, float scale, const char *overlaid = NULL, bool throttle = false) { return 0; }
+ virtual int playerpreview(int model, int team, int weap, float scale, const char *overlaid = NULL) = 0;
+ virtual int modelpreview(const char *name, int anim, float scale, const char *overlaid = NULL, bool throttle = false) = 0;
+ virtual int prefabpreview(const char *prefab, const vec &color, float scale, const char *overlaid = NULL, bool throttle = false) = 0;
virtual void slider(int &val, int vmin, int vmax, int color, const char *label = NULL) = 0;
virtual void separator() = 0;
- virtual void progress(float percent) = 0;
- virtual void strut(float size) = 0;
+ virtual void progress(float percent) = 0;
+ virtual void strut(float size) = 0;
virtual void space(float size) = 0;
virtual void spring(int weight = 1) = 0;
virtual void column(int col) = 0;
extern int reserveclients();
extern int numchannels();
extern void clientdisconnect(int n);
- extern int clientconnect(int n, uint ip);
+ extern int clientconnect(int n);
extern void localdisconnect(int n);
extern void localconnect(int n);
extern bool allowbroadcast(int n);
extern bool sendpackets(bool force = false);
extern void serverinforeply(ucharbuf &req, ucharbuf &p);
extern void serverupdate();
- extern bool servercompatible(char *name, char *sdec, char *map, int ping, const vector<int> &attr, int np);
extern int laninfoport();
extern int serverinfoport(int servport = -1);
extern int serverport(int infoport = -1);
{
if(dst >= dstend) goto done;
const uchar *end = min(srcend, &src[dstend-dst]);
- do
- {
+ do
+ {
if(uni == '\f')
{
if(++src >= srcend) goto done;
goto uni1;
}
- *dst++ = uni;
- if(++src >= end) goto done;
- uni = cube2uni(*src);
- }
+ *dst++ = uni;
+ if(++src >= end) goto done;
+ uni = cube2uni(*src);
+ }
while(uni <= 0x7F);
}
if(uni <= 0x7FF) { if(dst + 2 > dstend) goto done; *dst++ = 0xC0 | (uni>>6); goto uni2; }
uni3: *dst++ = 0x80 | ((uni>>6)&0x3F);
uni2: *dst++ = 0x80 | (uni&0x3F);
uni1:;
- }
+ }
while(++src < srcend);
done:
if(!filter) break;
if(filter > pdir && filter[-1] == PATHDIV && filter[len] == PATHDIV) break;
filter += len;
- }
+ }
packagedir &pf = packagedirs.add();
pf.dir = filter ? newstring(pdir, filter-pdir) : newstring(pdir);
pf.dirlen = filter ? filter-pdir : strlen(pdir);
if(!ext) files.add(newstring(FindFileData.cFileName));
else
{
- size_t namelen = strlen(FindFileData.cFileName);
- if(namelen > extsize)
- {
+ size_t namelen = strlen(FindFileData.cFileName);
+ if(namelen > extsize)
+ {
namelen -= extsize;
if(FindFileData.cFileName[namelen] == '.' && strncmp(FindFileData.cFileName+namelen+1, ext, extsize-1)==0)
files.add(newstring(FindFileData.cFileName, namelen));
char buf[512];
char *str = buf;
va_list args;
-#if defined(WIN32) && !defined(__GNUC__)
- va_start(args, fmt);
- int len = _vscprintf(fmt, args);
- if(len <= 0) { va_end(args); return 0; }
- if(len >= (int)sizeof(buf)) str = new char[len+1];
- _vsnprintf(str, len+1, fmt, args);
- va_end(args);
-#else
va_start(args, fmt);
int len = vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
vsnprintf(str, len+1, fmt, args);
va_end(args);
}
-#endif
size_t n = write(str, len);
if(str != buf) delete[] str;
return n;
bool opentemp(const char *name, const char *mode)
{
if(file) return false;
-#ifdef WIN32
- file = fopen(name, mode);
-#else
file = tmpfile();
-#endif
return file!=NULL;
}
}
bool end() { return feof(file)!=0; }
- offset tell()
- {
-#ifdef WIN32
-#if defined(__GNUC__) && !defined(__MINGW32__)
- offset off = ftello64(file);
-#else
- offset off = _ftelli64(file);
-#endif
-#else
+ offset tell()
+ {
offset off = ftello(file);
-#endif
- // ftello returns LONG_MAX for directories on some platforms
return off + 1 >= 0 ? off : -1;
}
- bool seek(offset pos, int whence)
- {
-#ifdef WIN32
-#if defined(__GNUC__) && !defined(__MINGW32__)
- return fseeko64(file, pos, whence) >= 0;
-#else
- return _fseeki64(file, pos, whence) >= 0;
-#endif
-#else
+ bool seek(offset pos, int whence = SEEK_SET)
+ {
return fseeko(file, pos, whence) >= 0;
-#endif
}
size_t read(void *buf, size_t len) { return fread(buf, 1, len, file); }
}
};
-#ifndef STANDALONE
-VAR(dbggz, 0, 0, 1);
-#endif
-
struct gzstream : stream
{
enum
void finishreading()
{
if(!reading) return;
-#ifndef STANDALONE
- if(dbggz)
- {
- uint checkcrc = 0, checksize = 0;
- loopi(4) checkcrc |= uint(readbyte()) << (i*8);
- loopi(4) checksize |= uint(readbyte()) << (i*8);
- if(checkcrc != crc)
- conoutf(CON_DEBUG, "gzip crc check failed: read %X, calculated %X", checkcrc, crc);
- if(checksize != zfile.total_out)
- conoutf(CON_DEBUG, "gzip size check failed: read %u, calculated %u", checksize, uint(zfile.total_out));
- }
-#endif
}
void stopreading()
offset pos;
size_t bufread, bufcarry, buflen;
bool reading, writing, autoclose;
- uchar buf[BUFSIZE];
+ uchar buf[BUFSIZE];
utf8stream() : file(NULL), pos(0), bufread(0), bufcarry(0), buflen(0), reading(false), writing(false), autoclose(false)
{
{
size_t n = file->read(buf, 3);
if(n == 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) return true;
- buflen = n;
+ buflen = n;
return false;
}
-
+
bool open(stream *f, const char *mode, bool needclose)
{
if(file) return false;
else if(*mode=='w') { writing = true; break; }
}
if(!reading && !writing) return false;
-
+
file = f;
-
+
if(reading) checkheader();
-
+
autoclose = needclose;
return true;
- }
+ }
- void finishreading()
+ void finishreading()
{
if(!reading) return;
}
return !off;
}
else if(whence == SEEK_CUR) off += pos;
-
+
if(off >= pos) off -= pos;
else if(off < 0 || !file->seek(0, SEEK_SET)) return false;
else
{
bufread = bufcarry = buflen = 0;
pos = 0;
- checkheader();
+ checkheader();
}
uchar skip[512];
if(read(skip, skipped) != skipped) { stopreading(); return false; }
off -= skipped;
}
-
+
return true;
}
if(bufread >= bufcarry) { if(readbuf(BUFSIZE)) continue; stopreading(); if(!next) return false; break; }
size_t n = min(len - next, bufcarry - bufread);
uchar *endline = (uchar *)memchr(&buf[bufread], '\n', n);
- if(endline) { n = endline+1 - &buf[bufread]; len = next + n; }
+ if(endline) { n = endline+1 - &buf[bufread]; len = next + n; }
memcpy(&((uchar *)dst)[next], &buf[bufread], n);
next += n;
bufread += n;
if(f->read(buf, 3) != 3) { delete f; delete[] buf; return NULL; }
if(((uchar *)buf)[0] == 0xEF && ((uchar *)buf)[1] == 0xBB && ((uchar *)buf)[2] == 0xBF) len -= 3;
else offset += 3;
- }
+ }
size_t rlen = f->read(&buf[offset], len-offset);
delete f;
if(rlen != len-offset) { delete[] buf; return NULL; }