--- monster.cpp 2005-08-14 16:16:00.000000000 +0200 +++ monster.cpp 2010-11-18 14:07:54.594877000 +0100 @@ -100,12 +100,12 @@ }; }; -bool los(float lx, float ly, float lz, float bx, float by, float bz, vec &v) // height-correct line of sight for monster shooting/seeing +bool los(float stepdiv, float lx, float ly, float lz, float bx, float by, float bz, vec &v) // height-correct line of sight for monster shooting/seeing { if(OUTBORD((int)lx, (int)ly) || OUTBORD((int)bx, (int)by)) return false; float dx = bx-lx; float dy = by-ly; - int steps = (int)(sqrt(dx*dx+dy*dy)/0.9); + int steps = (int)(sqrt(dx*dx+dy*dy)/stepdiv); if(!steps) return false; float x = lx; float y = ly; @@ -133,7 +133,7 @@ bool enemylos(dynent *m, vec &v) { v = m->o; - return los(m->o.x, m->o.y, m->o.z, m->enemy->o.x, m->enemy->o.y, m->enemy->o.z, v); + return los(0.9, m->o.x, m->o.y, m->o.z, m->enemy->o.x, m->enemy->o.y, m->enemy->o.z, v); }; // monster AI is sequenced using transitions: they are in a particular state where --- renderextras.cpp 2005-08-22 00:27:42.000000000 +0200 +++ renderextras.cpp 2010-11-18 14:01:26.757172000 +0100 @@ -195,6 +195,9 @@ glGetIntegerv(GL_VIEWPORT, viewport); glGetDoublev(GL_MODELVIEW_MATRIX, mm); glGetDoublev(GL_PROJECTION_MATRIX, pm); + vec r = { (float)mm[0], (float)mm[4], (float)mm[8] }; + vec u = { (float)mm[1], (float)mm[5], (float)mm[9] }; + setorient(r, u); }; // stupid function to cater for stupid ATI linux drivers that return incorrect depth values @@ -210,17 +213,79 @@ // also hits map entities which is unwanted. // could be replaced by a more acurate version of monster.cpp los() if needed +extern bool los(float stepdiv, float lx, float ly, float lz, float bx, float by, float bz, vec &v); +extern float rad(float x); + +bool intersectent(entity *e, vec &from, vec &to) // if lineseg hits entity bounding box +{ + mapmodelinfo &mmi = getmminfo(e->attr2); + if(!&mmi) return false; + float z = (float)S(e->x, e->y)->floor+mmi.zoff+e->attr3+mmi.h/2, radius = mmi.rad; + + vec v = to, w = { e->x, e->y, z }, o = w, *p; + vsub(v, from); + vsub(w, from); + float c1 = dotprod(w, v); + + if(c1<=0) p = &from; + else + { + float c2 = dotprod(v, v); + if(c2<=c1) p = &to; + else + { + float f = c1/c2; + vmul(v, f); + vadd(v, from); + p = &v; + } + } + + return p->x <= o.x+radius + && p->x >= o.x-radius + && p->y <= o.y+radius + && p->y >= o.y-radius + && p->z <= o.z+mmi.h/2 + && p->z >= o.z-mmi.h/2; +}; + void readdepth(int w, int h) { - glReadPixels(w/2, h/2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &cursordepth); - double worldx = 0, worldy = 0, worldz = 0; - gluUnProject(w/2, h/2, depthcorrect(cursordepth), mm, pm, viewport, &worldx, &worldz, &worldy); - worldpos.x = (float)worldx; - worldpos.y = (float)worldy; - worldpos.z = (float)worldz; - vec r = { (float)mm[0], (float)mm[4], (float)mm[8] }; - vec u = { (float)mm[1], (float)mm[5], (float)mm[9] }; - setorient(r, u); + float yaw = player1->yaw-90, pitch = -player1->pitch; + vec dir; + + float sin_yaw = sinf(rad(yaw)); + float cos_yaw = cosf(rad(yaw)); + + float sin_pitch = sinf(rad(pitch)); + float cos_pitch = cosf(rad(pitch)); + + dir.x = cos_pitch * cos_yaw; + dir.y = cos_pitch * sin_yaw; + dir.z = -sin_pitch; + + vadd(dir, player1->o); + + vec pos; + los(0.05, player1->o.x, player1->o.y, player1->o.z, dir.x, dir.y, dir.z, pos); + dir.x = pos.x-player1->o.x; + dir.y = pos.y-player1->o.y; + dir.z = pos.z-player1->o.z; + float dist = sqrt(dir.x*dir.x + dir.y*dir.y); + vmul(dir, 1/dist); + + loopv(ents) + { + entity &e = ents[i]; + if(e.type != MAPMODEL) continue; + vec eo = { e.x, e.y, e.z }; + vdist(curdist, v, eo, player1->o); + if(curdist < dist && intersectent(&e, player1->o, pos)) dist = curdist; + } + + vmul(dir, dist); + vadd(dir, player1->o); + worldpos = dir; }; void drawicon(float tx, float ty, int x, int y) @@ -267,7 +332,7 @@ readmatrices(); if(editmode) { - if(cursordepth==1.0f) worldpos = player1->o; + //if(cursordepth==1.0f) worldpos = player1->o; glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); cursorupdate(); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);