2004-08-23 00:15:46 +00:00
/*
Copyright ( C ) 1996 - 1997 Id Software , Inc .
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation ; either version 2
of the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*/
// world.c -- world query functions
2009-11-04 21:16:50 +00:00
# include "quakedef.h"
# include "pr_common.h"
2004-08-23 00:15:46 +00:00
2009-11-17 00:15:44 +00:00
# if defined(CSQC_DAT) || !defined(CLIENTONLY)
2004-08-23 00:15:46 +00:00
/*
entities never clip against themselves , or their owner
line of sight checks trace - > crosscontent , but bullets don ' t
*/
2017-08-29 02:29:06 +00:00
size_t areagridsequence ; //used to avoid poking the same ent twice.
2007-10-05 18:08:47 +00:00
extern cvar_t sv_compatiblehulls ;
2017-08-14 16:38:44 +00:00
extern cvar_t sv_gameplayfix_nolinknonsolid ;
2004-08-23 00:15:46 +00:00
typedef struct
{
vec3_t boxmins , boxmaxs ; // enclose the test object along entire move
float * mins , * maxs ; // size of the moving object
vec3_t mins2 , maxs2 ; // size when clipping against mosnters
float * start , * end ;
trace_t trace ;
int type ;
2012-01-17 07:57:46 +00:00
int hitcontentsmask ;
2009-11-04 21:16:50 +00:00
wedict_t * passedict ;
2004-08-23 00:15:46 +00:00
# ifdef Q2SERVER
q2edict_t * q2passedict ;
# endif
2014-09-17 03:04:08 +00:00
int hullnum ;
qboolean capsule ;
2004-08-23 00:15:46 +00:00
} moveclip_t ;
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
HULL BOXES
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
static hull_t box_hull ;
2011-06-29 18:39:11 +00:00
static mclipnode_t box_clipnodes [ 6 ] ;
2004-08-23 00:15:46 +00:00
static mplane_t box_planes [ 6 ] ;
/*
= = = = = = = = = = = = = = = = = = =
SV_InitBoxHull
Set up the planes and clipnodes so that the six floats of a bounding box
can just be stored out and get a proper hull_t structure .
= = = = = = = = = = = = = = = = = = =
*/
2009-11-04 21:16:50 +00:00
static void World_InitBoxHull ( void )
2004-08-23 00:15:46 +00:00
{
int i ;
int side ;
box_hull . clipnodes = box_clipnodes ;
box_hull . planes = box_planes ;
box_hull . firstclipnode = 0 ;
box_hull . lastclipnode = 5 ;
for ( i = 0 ; i < 6 ; i + + )
{
box_clipnodes [ i ] . planenum = i ;
side = i & 1 ;
box_clipnodes [ i ] . children [ side ] = Q1CONTENTS_EMPTY ;
if ( i ! = 5 )
box_clipnodes [ i ] . children [ side ^ 1 ] = i + 1 ;
else
box_clipnodes [ i ] . children [ side ^ 1 ] = Q1CONTENTS_SOLID ;
box_planes [ i ] . type = i > > 1 ;
box_planes [ i ] . normal [ i > > 1 ] = 1 ;
}
}
/*
= = = = = = = = = = = = = = = = = = =
SV_HullForBox
To keep everything totally uniform , bounding boxes are turned into small
BSP trees instead of being compared directly .
= = = = = = = = = = = = = = = = = = =
*/
2012-07-05 19:42:36 +00:00
hull_t * World_HullForBox ( vec3_t mins , vec3_t maxs )
2004-08-23 00:15:46 +00:00
{
box_planes [ 0 ] . dist = maxs [ 0 ] ;
box_planes [ 1 ] . dist = mins [ 0 ] ;
box_planes [ 2 ] . dist = maxs [ 1 ] ;
box_planes [ 3 ] . dist = mins [ 1 ] ;
box_planes [ 4 ] . dist = maxs [ 2 ] ;
box_planes [ 5 ] . dist = mins [ 2 ] ;
return & box_hull ;
}
2014-09-17 03:04:08 +00:00
model_t mod_capsule ;
qboolean World_BoxTrace ( struct model_s * model , int hulloverride , int frame , vec3_t axis [ 3 ] , vec3_t p1 , vec3_t p2 , vec3_t mins , vec3_t maxs , unsigned int against , struct trace_s * trace )
{
2014-09-20 04:11:39 +00:00
hull_t * hull = & box_hull ;
//bbox vs bbox
2014-09-17 03:04:08 +00:00
//capsule vs bbox (NYI)
2014-09-20 04:11:39 +00:00
memset ( trace , 0 , sizeof ( trace_t ) ) ;
trace - > fraction = 1 ;
trace - > allsolid = true ;
VectorCopy ( p2 , trace - > endpos ) ;
return Q1BSP_RecursiveHullCheck ( hull , hull - > firstclipnode , 0 , 1 , p1 , p2 , trace ) ;
2014-09-17 03:04:08 +00:00
}
2016-12-19 13:31:05 +00:00
qboolean World_CapsuleTrace ( struct model_s * model , int hulloverride , framestate_t * framestate , vec3_t axis [ 3 ] , vec3_t p1 , vec3_t p2 , vec3_t mins , vec3_t maxs , qboolean capsule , unsigned int against , struct trace_s * trace )
2014-09-17 03:04:08 +00:00
{
//bbox vs capsule (NYI)
//capsule vs capsule (NYI)
2014-09-20 04:11:39 +00:00
memset ( trace , 0 , sizeof ( trace_t ) ) ;
trace - > fraction = 1 ;
trace - > allsolid = false ;
VectorCopy ( p2 , trace - > endpos ) ;
if ( capsule )
{ //capsule vs capsule.
//no orientation support on either (ignore axis)
float sr = ( ( model - > maxs [ 0 ] - model - > mins [ 0 ] ) + ( model - > maxs [ 1 ] - model - > mins [ 1 ] ) ) / 4.0 ;
float sh = ( model - > maxs [ 2 ] - model - > mins [ 2 ] ) - sr * 2 ;
float mr = ( ( maxs [ 0 ] - mins [ 0 ] ) + ( maxs [ 1 ] - mins [ 1 ] ) ) / 4.0 ;
float mh = ( maxs [ 2 ] - mins [ 2 ] ) - mr * 2 ;
vec3_t sup = { 0 , 0 , 1 } ;
vec3_t dir , sright ;
vec4_t nearestplane ;
float d1 , d2 ;
vec3_t nearestpoint ;
float neardist ;
//expand the static capsule's height+radius by the mover's height+radius, so that its point+capsule instead
sr + = mr ;
sh + = mh ;
VectorSubtract ( p1 , p2 , dir ) ;
d2 = VectorNormalize ( dir ) ;
CrossProduct ( sup , dir , sright ) ;
VectorNormalize ( sright ) ;
CrossProduct ( sup , sright , nearestplane ) ;
VectorNormalize ( nearestplane ) ;
nearestplane [ 3 ] = DotProduct ( vec3_origin , nearestplane ) ; //capsule is at 0 0 0
d1 = DotProduct ( nearestplane , p1 ) - nearestplane [ 3 ] ;
d2 = DotProduct ( nearestplane , p2 ) - nearestplane [ 3 ] ;
d2 = - d1 / ( d1 + d2 ) ;
VectorInterpolate ( p1 , d2 , p2 , nearestpoint ) ;
neardist = VectorLength ( nearestpoint ) ;
if ( neardist < sr )
{
float x , y , oz , nz ;
//sqrt(h*h-(x*x+y*y))=z
//change the hypotenuse from the messed up value to the actual radius
//and update z to match the changed h
x = DotProduct ( sup , nearestpoint ) - 0 ;
y = DotProduct ( sright , nearestpoint ) - 0 ;
oz = DotProduct ( nearestplane , nearestpoint ) - nearestplane [ 3 ] ;
nz = sqrt ( sr * sr - ( x * x + y * y ) ) ;
VectorMA ( nearestpoint , nz - oz , dir , trace - > endpos ) ;
trace - > fraction = 0 ;
}
}
2014-09-17 03:04:08 +00:00
return false ;
}
model_t * World_CapsuleForBox ( vec3_t mins , vec3_t maxs )
{
VectorCopy ( mins , mod_capsule . mins ) ;
VectorCopy ( maxs , mod_capsule . maxs ) ;
mod_capsule . funcs . NativeTrace = World_CapsuleTrace ;
return & mod_capsule ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
ENTITY AREA CHECKING
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2017-08-29 02:29:06 +00:00
# if defined(Q2SERVER) || !defined(USEAREAGRID)
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = =
SV_CreateAreaNode
= = = = = = = = = = = = = = =
*/
2009-11-04 21:16:50 +00:00
static areanode_t * World_CreateAreaNode ( world_t * w , int depth , vec3_t mins , vec3_t maxs )
2004-08-23 00:15:46 +00:00
{
areanode_t * anode ;
vec3_t size ;
vec3_t mins1 , maxs1 , mins2 , maxs2 ;
2009-11-04 21:16:50 +00:00
anode = & w - > areanodes [ w - > numareanodes ] ;
w - > numareanodes + + ;
2004-08-23 00:15:46 +00:00
2011-06-29 18:39:11 +00:00
ClearLink ( & anode - > edicts ) ;
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
VectorSubtract ( maxs , mins , size ) ;
if ( depth = = w - > areanodedepth | | ( size [ 0 ] < 512 & & size [ 1 ] < 512 ) )
2004-08-23 00:15:46 +00:00
{
anode - > axis = - 1 ;
anode - > children [ 0 ] = anode - > children [ 1 ] = NULL ;
return anode ;
}
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
2004-08-23 00:15:46 +00:00
if ( size [ 0 ] > size [ 1 ] )
anode - > axis = 0 ;
else
anode - > axis = 1 ;
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
2004-08-23 00:15:46 +00:00
anode - > dist = 0.5 * ( maxs [ anode - > axis ] + mins [ anode - > axis ] ) ;
VectorCopy ( mins , mins1 ) ;
VectorCopy ( mins , mins2 ) ;
VectorCopy ( maxs , maxs1 ) ;
VectorCopy ( maxs , maxs2 ) ;
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
2004-08-23 00:15:46 +00:00
maxs1 [ anode - > axis ] = mins2 [ anode - > axis ] = anode - > dist ;
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
2009-11-04 21:16:50 +00:00
anode - > children [ 0 ] = World_CreateAreaNode ( w , depth + 1 , mins2 , maxs2 ) ;
anode - > children [ 1 ] = World_CreateAreaNode ( w , depth + 1 , mins1 , maxs1 ) ;
2004-08-23 00:15:46 +00:00
return anode ;
}
/*
= = = = = = = = = = = = = = =
SV_ClearWorld
= = = = = = = = = = = = = = =
*/
2017-08-29 02:29:06 +00:00
void World_ClearWorld_Nodes ( world_t * w , qboolean relink )
2004-08-23 00:15:46 +00:00
{
2017-08-29 02:29:06 +00:00
# if !defined(USEAREAGRID)
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
int i ;
wedict_t * ent ;
2017-08-29 02:29:06 +00:00
# endif
2015-06-12 14:44:50 +00:00
int maxdepth ;
vec3_t mins , maxs ;
if ( w - > worldmodel )
{
VectorCopy ( w - > worldmodel - > mins , mins ) ;
VectorCopy ( w - > worldmodel - > maxs , maxs ) ;
}
else
{
VectorSet ( mins , - 4096 , - 4096 , - 4096 ) ;
VectorSet ( maxs , 4096 , 4096 , 4096 ) ;
}
2009-11-04 21:16:50 +00:00
World_InitBoxHull ( ) ;
2017-08-29 02:29:06 +00:00
# if !defined(USEAREAGRID)
2014-07-12 06:56:17 +00:00
memset ( & w - > portallist , 0 , sizeof ( w - > portallist ) ) ;
ClearLink ( & w - > portallist . edicts ) ;
w - > portallist . axis = - 1 ;
2017-08-29 02:29:06 +00:00
# endif
2014-07-12 06:56:17 +00:00
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
maxdepth = 8 ;
2015-06-12 14:44:50 +00:00
if ( ! w - > areanodes | | w - > areanodedepth ! = maxdepth )
2009-11-07 13:29:15 +00:00
{
2015-06-12 14:44:50 +00:00
Z_Free ( w - > areanodes ) ;
w - > areanodedepth = maxdepth ;
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
w - > areanodes = Z_Malloc ( sizeof ( * w - > areanodes ) * ( pow ( 2 , w - > areanodedepth + 1 ) - 1 ) ) ;
2009-11-07 13:29:15 +00:00
}
else
2015-09-10 10:16:26 +00:00
memset ( w - > areanodes , 0 , sizeof ( * w - > areanodes ) * w - > numareanodes ) ;
2015-06-12 14:44:50 +00:00
w - > numareanodes = 0 ;
World_CreateAreaNode ( w , 0 , mins , maxs ) ;
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
2017-08-29 02:29:06 +00:00
# if !defined(USEAREAGRID)
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
if ( relink )
{
for ( i = 0 ; i < w - > num_edicts ; i + + )
{
ent = WEDICT_NUM ( w - > progs , i ) ;
if ( ! ent )
continue ;
ent - > area . prev = ent - > area . next = NULL ;
if ( ED_ISFREE ( ent ) )
continue ;
World_LinkEdict ( w , ent , false ) ; // relink ents so touch functions continue to work.
}
}
2017-08-29 02:29:06 +00:00
# endif
}
2017-08-29 04:46:53 +00:00
# endif
2017-08-29 02:29:06 +00:00
# ifdef USEAREAGRID
static void World_ClearWorld_AreaGrid ( world_t * w , qboolean relink )
{
int numareas = 1 ;
int i , j ;
wedict_t * ent ;
vec3_t mins , maxs , size ;
if ( w - > worldmodel )
{
VectorCopy ( w - > worldmodel - > mins , mins ) ;
VectorCopy ( w - > worldmodel - > maxs , maxs ) ;
}
else
{
VectorSet ( mins , - 4096 , - 4096 , - 4096 ) ;
VectorSet ( maxs , 4096 , 4096 , 4096 ) ;
}
Vector2Set ( w - > gridsize , 128 , 128 ) ;
for ( i = 0 ; i < 2 ; i + + )
{
size [ i ] = maxs [ i ] - mins [ i ] ;
size [ i ] / = w - > gridsize [ i ] ;
//enforce a minimum grid size, so things don't end up getting added to every single node
if ( size [ i ] < 128 )
size [ i ] = 128 ;
w - > gridscale [ i ] = size [ i ] ;
w - > gridbias [ i ] = - mins [ i ] ;
numareas * = w - > gridsize [ i ] ;
}
World_InitBoxHull ( ) ;
if ( w - > gridareas )
memset ( w - > gridareas , 0 , sizeof ( * w - > gridareas ) * numareas ) ;
else
w - > gridareas = Z_Malloc ( sizeof ( * w - > gridareas ) * numareas ) ;
for ( i = 0 ; i < numareas ; i + + )
ClearLink ( & w - > gridareas [ i ] . l ) ;
ClearLink ( & w - > jumboarea . l ) ;
ClearLink ( & w - > portallist . l ) ;
if ( relink )
{
for ( i = 0 ; i < w - > num_edicts ; i + + )
{
ent = WEDICT_NUM ( w - > progs , i ) ;
if ( ! ent )
continue ;
for ( j = 0 ; j < countof ( ent - > gridareas ) ; j + + )
{
if ( ! ent - > gridareas [ j ] . l . prev )
break ; // not linked in anywhere
ClearLink ( & ent - > gridareas [ j ] . l ) ;
}
if ( ED_ISFREE ( ent ) )
continue ;
World_LinkEdict ( w , ent , false ) ; // relink ents so touch functions continue to work.
}
}
2004-08-23 00:15:46 +00:00
}
2017-08-29 02:29:06 +00:00
# endif
2004-08-23 00:15:46 +00:00
2017-08-29 02:29:06 +00:00
void World_ClearWorld ( world_t * w , qboolean relink )
{
# ifdef Q2SERVER
if ( w = = & sv . world & & svs . gametype = = GT_QUAKE2 )
World_ClearWorld_Nodes ( w , relink ) ;
else
# endif
{
# ifdef USEAREAGRID
World_ClearWorld_AreaGrid ( w , relink ) ;
# else
World_ClearWorld_Nodes ( w , relink ) ;
# endif
}
}
# if !defined(USEAREAGRID)
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = =
SV_UnlinkEdict
= = = = = = = = = = = = = = =
*/
2009-11-04 21:16:50 +00:00
void World_UnlinkEdict ( wedict_t * ent )
2004-08-23 00:15:46 +00:00
{
if ( ! ent - > area . prev )
return ; // not linked in anywhere
RemoveLink ( & ent - > area ) ;
ent - > area . prev = ent - > area . next = NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = =
SV_TouchLinks
= = = = = = = = = = = = = = = = = = = =
*/
2009-11-04 21:16:50 +00:00
void World_TouchLinks ( world_t * w , wedict_t * ent , areanode_t * node )
{
2017-08-29 02:29:06 +00:00
static wedict_t * nodelinks [ 256 ] ; //all this means is that any more than this will not touch. probably you won't have that many valid triggers
2004-08-23 00:15:46 +00:00
link_t * l , * next ;
2009-11-04 21:16:50 +00:00
wedict_t * touch ;
2004-08-23 00:15:46 +00:00
int linkcount = 0 , ln ;
//work out who they are first.
2011-06-29 18:39:11 +00:00
for ( l = node - > edicts . next ; l ! = & node - > edicts ; l = next )
2004-08-23 00:15:46 +00:00
{
2017-08-29 02:29:06 +00:00
if ( linkcount = = countof ( nodelinks ) )
2005-05-26 12:55:34 +00:00
break ;
2004-08-23 00:15:46 +00:00
next = l - > next ;
touch = EDICT_FROM_AREA ( l ) ;
if ( touch = = ent )
continue ;
2005-03-28 00:11:59 +00:00
if ( ! touch - > v - > touch | | touch - > v - > solid ! = SOLID_TRIGGER )
2004-08-23 00:15:46 +00:00
continue ;
2005-03-28 00:11:59 +00:00
if ( ent - > v - > absmin [ 0 ] > touch - > v - > absmax [ 0 ]
| | ent - > v - > absmin [ 1 ] > touch - > v - > absmax [ 1 ]
| | ent - > v - > absmin [ 2 ] > touch - > v - > absmax [ 2 ]
| | ent - > v - > absmax [ 0 ] < touch - > v - > absmin [ 0 ]
| | ent - > v - > absmax [ 1 ] < touch - > v - > absmin [ 1 ]
| | ent - > v - > absmax [ 2 ] < touch - > v - > absmin [ 2 ] )
2004-08-23 00:15:46 +00:00
continue ;
2007-09-02 19:55:17 +00:00
if ( ! ( ( int ) ent - > xv - > dimension_solid & ( int ) touch - > xv - > dimension_hit ) )
2004-08-31 23:58:18 +00:00
continue ;
2004-08-23 00:15:46 +00:00
nodelinks [ linkcount + + ] = touch ;
}
for ( ln = 0 ; ln < linkcount ; ln + + )
{
touch = nodelinks [ ln ] ;
//make sure nothing moved it away
2016-07-21 19:27:59 +00:00
if ( ED_ISFREE ( touch ) )
2004-08-23 00:15:46 +00:00
continue ;
2005-03-28 00:11:59 +00:00
if ( ! touch - > v - > touch | | touch - > v - > solid ! = SOLID_TRIGGER )
2004-08-23 00:15:46 +00:00
continue ;
2009-11-04 21:16:50 +00:00
2005-03-28 00:11:59 +00:00
if ( ent - > v - > absmin [ 0 ] > touch - > v - > absmax [ 0 ]
| | ent - > v - > absmin [ 1 ] > touch - > v - > absmax [ 1 ]
| | ent - > v - > absmin [ 2 ] > touch - > v - > absmax [ 2 ]
| | ent - > v - > absmax [ 0 ] < touch - > v - > absmin [ 0 ]
| | ent - > v - > absmax [ 1 ] < touch - > v - > absmin [ 1 ]
| | ent - > v - > absmax [ 2 ] < touch - > v - > absmin [ 2 ] )
2004-08-23 00:15:46 +00:00
continue ;
2007-09-02 19:55:17 +00:00
if ( ! ( ( int ) ent - > xv - > dimension_solid & ( int ) touch - > xv - > dimension_hit ) ) //didn't change did it?...
2004-08-31 23:58:18 +00:00
continue ;
2009-11-07 13:29:15 +00:00
w - > Event_Touch ( w , touch , ent ) ;
2004-09-04 17:51:20 +00:00
2016-07-21 19:27:59 +00:00
if ( ED_ISFREE ( ent ) )
2004-09-04 17:51:20 +00:00
break ;
2004-08-23 00:15:46 +00:00
}
// recurse down both sides
2016-07-21 19:27:59 +00:00
if ( node - > axis = = - 1 | | ED_ISFREE ( ent ) )
2004-08-23 00:15:46 +00:00
return ;
2009-11-04 21:16:50 +00:00
if ( ent - > v - > absmax [ node - > axis ] > node - > dist )
World_TouchLinks ( w , ent , node - > children [ 0 ] ) ;
if ( ent - > v - > absmin [ node - > axis ] < node - > dist )
World_TouchLinks ( w , ent , node - > children [ 1 ] ) ;
2004-08-23 00:15:46 +00:00
}
# endif
/*
= = = = = = = = = = = = = = =
SV_LinkEdict
= = = = = = = = = = = = = = =
*/
2015-02-02 08:01:53 +00:00
void QDECL World_LinkEdict ( world_t * w , wedict_t * ent , qboolean touch_triggers )
2004-08-23 00:15:46 +00:00
{
2017-08-29 02:29:06 +00:00
# ifdef USEAREAGRID
World_UnlinkEdict ( ent ) ; // unlink from old position
# else
2004-08-23 00:15:46 +00:00
areanode_t * node ;
if ( ent - > area . prev )
2009-11-04 21:16:50 +00:00
World_UnlinkEdict ( ent ) ; // unlink from old position
2017-08-29 02:29:06 +00:00
# endif
2011-12-05 15:23:40 +00:00
2009-11-04 21:16:50 +00:00
if ( ent = = w - > edicts )
2004-08-23 00:15:46 +00:00
return ; // don't add the world
2016-07-21 19:27:59 +00:00
if ( ED_ISFREE ( ent ) )
2004-08-23 00:15:46 +00:00
return ;
// set the abs box
2005-03-28 00:11:59 +00:00
if ( ent - > v - > solid = = SOLID_BSP & &
( ent - > v - > angles [ 0 ] | | ent - > v - > angles [ 1 ] | | ent - > v - > angles [ 2 ] ) )
2004-08-23 00:15:46 +00:00
{ // expand for rotation
2006-03-23 19:22:12 +00:00
# if 1
int i ;
float v ;
2006-04-02 03:47:06 +00:00
float max ;
2006-03-23 19:22:12 +00:00
//q2 method
max = 0 ;
for ( i = 0 ; i < 3 ; i + + )
{
v = fabs ( ent - > v - > mins [ i ] ) ;
if ( v > max )
max = v ;
v = fabs ( ent - > v - > maxs [ i ] ) ;
if ( v > max )
max = v ;
}
for ( i = 0 ; i < 3 ; i + + )
{
ent - > v - > absmin [ i ] = ent - > v - > origin [ i ] - max ;
ent - > v - > absmax [ i ] = ent - > v - > origin [ i ] + max ;
}
# else
2004-08-23 00:15:46 +00:00
int i ;
2004-10-18 10:46:06 +00:00
vec3_t f , r , u ;
vec3_t mn , mx ;
2006-03-23 19:22:12 +00:00
2004-10-18 10:46:06 +00:00
//we need to link to the correct leaves
2006-03-23 19:22:12 +00:00
AngleVectors ( ent - > v - > angles , f , r , u ) ;
2004-10-18 10:46:06 +00:00
2005-03-28 00:11:59 +00:00
mn [ 0 ] = DotProduct ( ent - > v - > mins , f ) ;
mn [ 1 ] = - DotProduct ( ent - > v - > mins , r ) ;
mn [ 2 ] = DotProduct ( ent - > v - > mins , u ) ;
2006-03-23 19:22:12 +00:00
2005-03-28 00:11:59 +00:00
mx [ 0 ] = DotProduct ( ent - > v - > maxs , f ) ;
mx [ 1 ] = - DotProduct ( ent - > v - > maxs , r ) ;
mx [ 2 ] = DotProduct ( ent - > v - > maxs , u ) ;
2004-10-18 10:46:06 +00:00
for ( i = 0 ; i < 3 ; i + + )
2004-08-23 00:15:46 +00:00
{
2004-10-18 10:46:06 +00:00
if ( mn [ i ] < mx [ i ] )
{
2005-03-28 00:11:59 +00:00
ent - > v - > absmin [ i ] = ent - > v - > origin [ i ] + mn [ i ] - 0.1 ;
ent - > v - > absmax [ i ] = ent - > v - > origin [ i ] + mx [ i ] + 0.1 ;
2004-10-18 10:46:06 +00:00
}
else
{ //box went inside out
2005-03-28 00:11:59 +00:00
ent - > v - > absmin [ i ] = ent - > v - > origin [ i ] + mx [ i ] - 0.1 ;
ent - > v - > absmax [ i ] = ent - > v - > origin [ i ] + mn [ i ] + 0.1 ;
2004-10-18 10:46:06 +00:00
}
2004-08-23 00:15:46 +00:00
}
2006-03-23 19:22:12 +00:00
# endif
2004-08-23 00:15:46 +00:00
}
2004-11-17 17:40:05 +00:00
else
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
VectorAdd ( ent - > v - > origin , ent - > v - > mins , ent - > v - > absmin ) ;
VectorAdd ( ent - > v - > origin , ent - > v - > maxs , ent - > v - > absmax ) ;
2004-08-23 00:15:46 +00:00
}
2017-07-28 01:49:25 +00:00
if ( ! ent - > v - > solid )
ent - > solidsize = ES_SOLID_BSP ;
else // if (1)///*ent->v->modelindex || */ent->v->model)
2016-07-12 00:40:13 +00:00
{
2017-02-19 00:15:42 +00:00
model_t * mod = w - > Get_CModel ( w , ent - > v - > modelindex ) ;
if ( mod & & mod - > type = = mod_brush )
2016-07-12 00:40:13 +00:00
ent - > solidsize = ES_SOLID_BSP ;
else
ent - > solidsize = COM_EncodeSize ( ent - > v - > mins , ent - > v - > maxs ) ;
}
2004-08-23 00:15:46 +00:00
//
// to make items easier to pick up and allow them to be grabbed off
// of shelves, the abs sizes are expanded
//
2005-03-28 00:11:59 +00:00
if ( ( int ) ent - > v - > flags & FL_ITEM )
2004-08-23 00:15:46 +00:00
{
2005-03-28 00:11:59 +00:00
ent - > v - > absmin [ 0 ] - = 15 ;
ent - > v - > absmin [ 1 ] - = 15 ;
2009-03-03 01:52:30 +00:00
ent - > v - > absmin [ 2 ] - = 1 ;
2005-03-28 00:11:59 +00:00
ent - > v - > absmax [ 0 ] + = 15 ;
ent - > v - > absmax [ 1 ] + = 15 ;
2009-03-03 01:52:30 +00:00
ent - > v - > absmax [ 2 ] + = 1 ;
2004-08-23 00:15:46 +00:00
}
else
{ // because movement is clipped an epsilon away from an actual edge,
// we must fully check even when bounding boxes don't quite touch
2005-03-28 00:11:59 +00:00
ent - > v - > absmin [ 0 ] - = 1 ;
ent - > v - > absmin [ 1 ] - = 1 ;
ent - > v - > absmin [ 2 ] - = 1 ;
ent - > v - > absmax [ 0 ] + = 1 ;
ent - > v - > absmax [ 1 ] + = 1 ;
ent - > v - > absmax [ 2 ] + = 1 ;
2004-08-23 00:15:46 +00:00
}
// link to PVS leafs
2014-10-05 20:04:11 +00:00
if ( w - > worldmodel & & w - > worldmodel - > loadstate = = MLS_LOADED & & w - > worldmodel - > funcs . FindTouchedLeafs )
2004-08-23 00:15:46 +00:00
{
2011-09-03 03:49:43 +00:00
w - > worldmodel - > funcs . FindTouchedLeafs ( w - > worldmodel , & ent - > pvsinfo , ent - > v - > absmin , ent - > v - > absmax ) ;
2004-08-23 00:15:46 +00:00
}
2017-08-14 16:38:44 +00:00
if ( ent - > v - > solid = = SOLID_NOT & & ! sv_gameplayfix_nolinknonsolid . ival )
return ;
2014-08-17 02:27:54 +00:00
2017-08-29 02:29:06 +00:00
# ifdef USEAREAGRID
// find the first node that the ent's box crosses
if ( ent - > v - > solid = = SOLID_PORTAL )
{
ent - > gridareas [ 0 ] . ed = ent ;
InsertLinkBefore ( & ent - > gridareas [ 0 ] . l , & w - > portallist . l ) ;
}
else
{
int ming [ 2 ] , maxg [ 2 ] , g [ 2 ] , ga ;
CALCAREAGRIDBOUNDS ( w , ent - > v - > absmin , ent - > v - > absmax ) ;
if ( ( maxg [ 0 ] - ming [ 0 ] ) * ( maxg [ 1 ] - ming [ 1 ] ) > countof ( ent - > gridareas ) )
{ //entity is too large to fit in our grid. shove it in the overflow
ent - > gridareas [ 0 ] . ed = ent ;
InsertLinkBefore ( & ent - > gridareas [ 0 ] . l , & w - > jumboarea . l ) ;
}
else
{
for ( ga = 0 , g [ 0 ] = ming [ 0 ] ; g [ 0 ] < maxg [ 0 ] ; g [ 0 ] + + )
for ( g [ 1 ] = ming [ 1 ] ; g [ 1 ] < maxg [ 1 ] ; g [ 1 ] + + , ga + + )
{
ent - > gridareas [ ga ] . ed = ent ;
InsertLinkBefore ( & ent - > gridareas [ ga ] . l , & w - > gridareas [ g [ 0 ] + g [ 1 ] * w - > gridsize [ 0 ] ] . l ) ;
}
}
}
# else
2004-08-23 00:15:46 +00:00
// find the first node that the ent's box crosses
2014-07-12 06:56:17 +00:00
if ( ent - > v - > solid = = SOLID_PORTAL )
node = & w - > portallist ;
else
2004-08-23 00:15:46 +00:00
{
2014-07-12 06:56:17 +00:00
node = w - > areanodes ;
while ( 1 )
{
if ( node - > axis = = - 1 )
break ;
if ( ent - > v - > absmin [ node - > axis ] > node - > dist )
node = node - > children [ 0 ] ;
else if ( ent - > v - > absmax [ node - > axis ] < node - > dist )
node = node - > children [ 1 ] ;
else
break ; // crosses the node
}
2004-08-23 00:15:46 +00:00
}
// link it in
2011-06-29 18:39:11 +00:00
InsertLinkBefore ( & ent - > area , & node - > edicts ) ;
2017-08-29 02:29:06 +00:00
# endif
2004-08-23 00:15:46 +00:00
// if touch_triggers, touch all entities at this node and decend for more
2014-01-17 23:28:48 +00:00
if ( touch_triggers & & ent - > v - > solid ! = SOLID_NOT )
2017-08-29 02:29:06 +00:00
World_TouchAllLinks ( w , ent ) ;
2004-08-23 00:15:46 +00:00
}
# ifdef Q2SERVER
2009-11-04 21:16:50 +00:00
void VARGS WorldQ2_UnlinkEdict ( world_t * w , q2edict_t * ent )
2004-08-23 00:15:46 +00:00
{
if ( ! ent - > area . prev )
return ; // not linked in anywhere
RemoveLink ( & ent - > area ) ;
ent - > area . prev = ent - > area . next = NULL ;
}
2009-11-04 21:16:50 +00:00
void VARGS WorldQ2_LinkEdict ( world_t * w , q2edict_t * ent )
2004-08-23 00:15:46 +00:00
{
areanode_t * node ;
2017-08-29 02:29:06 +00:00
int leafs [ 128 ] ;
int clusters [ countof ( leafs ) ] ;
2004-08-23 00:15:46 +00:00
int num_leafs ;
2016-07-12 00:40:13 +00:00
int i , j ;
2004-08-23 00:15:46 +00:00
int area ;
int topnode ;
if ( ent - > area . prev )
2009-11-04 21:16:50 +00:00
WorldQ2_UnlinkEdict ( w , ent ) ; // unlink from old position
2004-08-23 00:15:46 +00:00
if ( ent = = ge - > edicts )
return ; // don't add the world
if ( ! ent - > inuse )
return ;
// set the size
VectorSubtract ( ent - > maxs , ent - > mins , ent - > size ) ;
// encode the size into the entity_state for client prediction
if ( ent - > solid = = Q2SOLID_BBOX & & ! ( ent - > svflags & SVF_DEADMONSTER ) )
{ // assume that x/y are equal and symetric
2016-07-12 00:40:13 +00:00
ent - > s . solid = COM_EncodeSize ( ent - > mins , ent - > maxs ) ;
/*
2004-08-23 00:15:46 +00:00
i = ent - > maxs [ 0 ] / 8 ;
if ( i < 1 )
i = 1 ;
if ( i > 31 )
i = 31 ;
// z is not symetric
j = ( - ent - > mins [ 2 ] ) / 8 ;
if ( j < 1 )
j = 1 ;
if ( j > 31 )
j = 31 ;
// and z maxs can be negative...
k = ( ent - > maxs [ 2 ] + 32 ) / 8 ;
if ( k < 1 )
k = 1 ;
if ( k > 63 )
k = 63 ;
2016-07-12 00:40:13 +00:00
//fixme: 32bit?
ent - > s . solid = ( k < < 10 ) | ( j < < 5 ) | i ; */
2004-08-23 00:15:46 +00:00
}
else if ( ent - > solid = = Q2SOLID_BSP )
{
2016-07-12 00:40:13 +00:00
ent - > s . solid = ES_SOLID_BSP ; // a solid_bbox will never create this value
2004-08-23 00:15:46 +00:00
}
else
ent - > s . solid = 0 ;
// set the abs box
if ( ent - > solid = = Q2SOLID_BSP & &
( ent - > s . angles [ 0 ] | | ent - > s . angles [ 1 ] | | ent - > s . angles [ 2 ] ) )
{ // expand for rotation
float max , v ;
int i ;
max = 0 ;
for ( i = 0 ; i < 3 ; i + + )
{
v = fabs ( ent - > mins [ i ] ) ;
if ( v > max )
max = v ;
v = fabs ( ent - > maxs [ i ] ) ;
if ( v > max )
max = v ;
}
for ( i = 0 ; i < 3 ; i + + )
{
ent - > absmin [ i ] = ent - > s . origin [ i ] - max ;
ent - > absmax [ i ] = ent - > s . origin [ i ] + max ;
}
}
else
{ // normal
VectorAdd ( ent - > s . origin , ent - > mins , ent - > absmin ) ;
VectorAdd ( ent - > s . origin , ent - > maxs , ent - > absmax ) ;
}
// because movement is clipped an epsilon away from an actual edge,
// we must fully check even when bounding boxes don't quite touch
ent - > absmin [ 0 ] - = 1 ;
ent - > absmin [ 1 ] - = 1 ;
ent - > absmin [ 2 ] - = 1 ;
ent - > absmax [ 0 ] + = 1 ;
ent - > absmax [ 1 ] + = 1 ;
ent - > absmax [ 2 ] + = 1 ;
// link to PVS leafs
ent - > num_clusters = 0 ;
ent - > areanum = 0 ;
ent - > areanum2 = 0 ;
//get all leafs, including solids
2009-11-04 21:16:50 +00:00
num_leafs = CM_BoxLeafnums ( w - > worldmodel , ent - > absmin , ent - > absmax ,
2017-08-29 02:29:06 +00:00
leafs , countof ( leafs ) , & topnode ) ;
2004-08-23 00:15:46 +00:00
// set areas
for ( i = 0 ; i < num_leafs ; i + + )
{
2009-11-04 21:16:50 +00:00
clusters [ i ] = CM_LeafCluster ( w - > worldmodel , leafs [ i ] ) ;
area = CM_LeafArea ( w - > worldmodel , leafs [ i ] ) ;
2004-08-23 00:15:46 +00:00
if ( area )
{ // doors may legally straggle two areas,
// but nothing should evern need more than that
if ( ent - > areanum & & ent - > areanum ! = area )
ent - > areanum2 = area ;
else
ent - > areanum = area ;
}
}
2017-08-29 02:29:06 +00:00
if ( num_leafs > = countof ( leafs ) )
2004-08-23 00:15:46 +00:00
{ // assume we missed some leafs, and mark by headnode
ent - > num_clusters = - 1 ;
ent - > headnode = topnode ;
}
else
{
ent - > num_clusters = 0 ;
for ( i = 0 ; i < num_leafs ; i + + )
{
if ( clusters [ i ] = = - 1 )
continue ; // not a visible leaf
for ( j = 0 ; j < i ; j + + )
if ( clusters [ j ] = = clusters [ i ] )
break ;
if ( j = = i )
{
if ( ent - > num_clusters = = MAX_ENT_CLUSTERS )
{ // assume we missed some leafs, and mark by headnode
ent - > num_clusters = - 1 ;
ent - > headnode = topnode ;
break ;
}
ent - > clusternums [ ent - > num_clusters + + ] = clusters [ i ] ;
}
}
}
// if first time, make sure old_origin is valid
if ( ! ent - > linkcount )
{
VectorCopy ( ent - > s . origin , ent - > s . old_origin ) ;
}
ent - > linkcount + + ;
if ( ent - > solid = = Q2SOLID_NOT )
return ;
// find the first node that the ent's box crosses
2009-11-04 21:16:50 +00:00
node = w - > areanodes ;
2004-08-23 00:15:46 +00:00
while ( 1 )
{
if ( node - > axis = = - 1 )
break ;
if ( ent - > absmin [ node - > axis ] > node - > dist )
node = node - > children [ 0 ] ;
else if ( ent - > absmax [ node - > axis ] < node - > dist )
node = node - > children [ 1 ] ;
else
break ; // crosses the node
}
// link it in
2011-06-29 18:39:11 +00:00
InsertLinkBefore ( & ent - > area , & node - > edicts ) ;
2004-08-23 00:15:46 +00:00
}
2009-11-04 21:16:50 +00:00
void WorldQ2_Q1BSP_LinkEdict ( world_t * w , q2edict_t * ent )
2004-08-23 00:15:46 +00:00
{
areanode_t * node ;
int i , j , k ;
if ( ent - > area . prev )
2009-11-04 21:16:50 +00:00
WorldQ2_UnlinkEdict ( w , ent ) ; // unlink from old position
2004-08-23 00:15:46 +00:00
if ( ent = = ge - > edicts )
return ; // don't add the world
if ( ! ent - > inuse )
return ;
// set the size
VectorSubtract ( ent - > maxs , ent - > mins , ent - > size ) ;
// encode the size into the entity_state for client prediction
if ( ent - > solid = = Q2SOLID_BBOX & & ! ( ent - > svflags & SVF_DEADMONSTER ) )
{ // assume that x/y are equal and symetric
i = ent - > maxs [ 0 ] / 8 ;
if ( i < 1 )
i = 1 ;
if ( i > 31 )
i = 31 ;
// z is not symetric
j = ( - ent - > mins [ 2 ] ) / 8 ;
if ( j < 1 )
j = 1 ;
if ( j > 31 )
j = 31 ;
// and z maxs can be negative...
k = ( ent - > maxs [ 2 ] + 32 ) / 8 ;
if ( k < 1 )
k = 1 ;
if ( k > 63 )
k = 63 ;
ent - > s . solid = ( k < < 10 ) | ( j < < 5 ) | i ;
}
else if ( ent - > solid = = Q2SOLID_BSP )
{
ent - > s . solid = 31 ; // a solid_bbox will never create this value
}
else
ent - > s . solid = 0 ;
// set the abs box
if ( ent - > solid = = Q2SOLID_BSP & &
( ent - > s . angles [ 0 ] | | ent - > s . angles [ 1 ] | | ent - > s . angles [ 2 ] ) )
{ // expand for rotation
float max , v ;
int i ;
max = 0 ;
for ( i = 0 ; i < 3 ; i + + )
{
v = fabs ( ent - > mins [ i ] ) ;
if ( v > max )
max = v ;
v = fabs ( ent - > maxs [ i ] ) ;
if ( v > max )
max = v ;
}
for ( i = 0 ; i < 3 ; i + + )
{
ent - > absmin [ i ] = ent - > s . origin [ i ] - max ;
ent - > absmax [ i ] = ent - > s . origin [ i ] + max ;
}
}
else
{ // normal
VectorAdd ( ent - > s . origin , ent - > mins , ent - > absmin ) ;
VectorAdd ( ent - > s . origin , ent - > maxs , ent - > absmax ) ;
}
// because movement is clipped an epsilon away from an actual edge,
// we must fully check even when bounding boxes don't quite touch
ent - > absmin [ 0 ] - = 1 ;
ent - > absmin [ 1 ] - = 1 ;
ent - > absmin [ 2 ] - = 1 ;
ent - > absmax [ 0 ] + = 1 ;
ent - > absmax [ 1 ] + = 1 ;
ent - > absmax [ 2 ] + = 1 ;
// link to PVS leafs
ent - > num_clusters = 0 ;
ent - > areanum = 0 ;
ent - > areanum2 = 0 ;
ent - > areanum = 1 ;
/*
//get all leafs, including solids
num_leafs = CM_BoxLeafnums ( ent - > absmin , ent - > absmax ,
leafs , MAX_TOTAL_ENT_LEAFS , & topnode ) ;
// set areas
for ( i = 0 ; i < num_leafs ; i + + )
{
clusters [ i ] = CM_LeafCluster ( leafs [ i ] ) ;
area = CM_LeafArea ( leafs [ i ] ) ;
if ( area )
{ // doors may legally straggle two areas,
// but nothing should evern need more than that
if ( ent - > areanum & & ent - > areanum ! = area )
{
ent - > areanum2 = area ;
}
else
ent - > areanum = area ;
}
}
if ( num_leafs > = MAX_TOTAL_ENT_LEAFS )
{ // assume we missed some leafs, and mark by headnode
ent - > num_clusters = - 1 ;
ent - > headnode = topnode ;
}
else
{
ent - > num_clusters = 0 ;
for ( i = 0 ; i < num_leafs ; i + + )
{
if ( clusters [ i ] = = - 1 )
continue ; // not a visible leaf
for ( j = 0 ; j < i ; j + + )
if ( clusters [ j ] = = clusters [ i ] )
break ;
if ( j = = i )
{
if ( ent - > num_clusters = = MAX_ENT_CLUSTERS )
{ // assume we missed some leafs, and mark by headnode
ent - > num_clusters = - 1 ;
ent - > headnode = topnode ;
break ;
}
ent - > clusternums [ ent - > num_clusters + + ] = clusters [ i ] ;
}
}
}
*/
// if first time, make sure old_origin is valid
if ( ! ent - > linkcount )
{
VectorCopy ( ent - > s . origin , ent - > s . old_origin ) ;
}
ent - > linkcount + + ;
if ( ent - > solid = = Q2SOLID_NOT )
return ;
// find the first node that the ent's box crosses
2009-11-04 21:16:50 +00:00
node = w - > areanodes ;
2004-08-23 00:15:46 +00:00
while ( 1 )
{
if ( node - > axis = = - 1 )
break ;
if ( ent - > absmin [ node - > axis ] > node - > dist )
node = node - > children [ 0 ] ;
else if ( ent - > absmax [ node - > axis ] < node - > dist )
node = node - > children [ 1 ] ;
else
break ; // crosses the node
}
2011-06-29 18:39:11 +00:00
// link it in
InsertLinkBefore ( & ent - > area , & node - > edicts ) ;
2004-08-23 00:15:46 +00:00
}
# endif
2017-08-29 02:29:06 +00:00
# if defined(Q2BSPS) || defined(Q3BSPS)
void Q23BSP_FindTouchedLeafs ( model_t * model , struct pvscache_s * ent , float * mins , float * maxs )
{
# define MAX_TOTAL_ENT_LEAFS 128
int leafs [ MAX_TOTAL_ENT_LEAFS ] ;
int clusters [ MAX_TOTAL_ENT_LEAFS ] ;
int num_leafs ;
int topnode ;
int i , j ;
int area ;
int nullarea = ( model - > fromgame = = fg_quake2 ) ? 0 : - 1 ;
//ent->num_leafs == q2's ent->num_clusters
ent - > num_leafs = 0 ;
ent - > areanum = nullarea ;
ent - > areanum2 = nullarea ;
if ( ! mins | | ! maxs )
return ;
//get all leafs, including solids
num_leafs = CM_BoxLeafnums ( model , mins , maxs ,
leafs , MAX_TOTAL_ENT_LEAFS , & topnode ) ;
// set areas
for ( i = 0 ; i < num_leafs ; i + + )
{
clusters [ i ] = CM_LeafCluster ( model , leafs [ i ] ) ;
area = CM_LeafArea ( model , leafs [ i ] ) ;
if ( area ! = nullarea )
{ // doors may legally straggle two areas,
// but nothing should ever need more than that
if ( ent - > areanum ! = nullarea & & ent - > areanum ! = area )
ent - > areanum2 = area ;
else
ent - > areanum = area ;
}
}
if ( num_leafs > = MAX_TOTAL_ENT_LEAFS )
{ // assume we missed some leafs, and mark by headnode
ent - > num_leafs = - 1 ;
ent - > headnode = topnode ;
}
else
{
ent - > num_leafs = 0 ;
for ( i = 0 ; i < num_leafs ; i + + )
{
if ( clusters [ i ] = = - 1 )
continue ; // not a visible leaf
for ( j = 0 ; j < i ; j + + )
if ( clusters [ j ] = = clusters [ i ] )
break ;
if ( j = = i )
{
if ( ent - > num_leafs = = MAX_ENT_LEAFS )
{ // assume we missed some leafs, and mark by headnode
ent - > num_leafs = - 1 ;
ent - > headnode = topnode ;
break ;
}
ent - > leafnums [ ent - > num_leafs + + ] = clusters [ i ] ;
}
}
}
}
# endif
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
POINT TESTING IN HULLS
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/*
= = = = = = = = = = = = = = = = = =
SV_PointContents
= = = = = = = = = = = = = = = = = =
*/
2009-11-04 21:16:50 +00:00
int World_PointContents ( world_t * w , vec3_t p )
2004-08-23 00:15:46 +00:00
{
2010-08-28 17:14:38 +00:00
return w - > worldmodel - > funcs . PointContents ( w - > worldmodel , NULL , p ) ;
2004-08-23 00:15:46 +00:00
}
//===========================================================================
/*
= = = = = = = = = = = =
SV_TestEntityPosition
A small wrapper around SV_BoxInSolidEntity that never clips against the
supplied entity .
= = = = = = = = = = = =
*/
2009-11-04 21:16:50 +00:00
wedict_t * World_TestEntityPosition ( world_t * w , wedict_t * ent )
2004-08-23 00:15:46 +00:00
{
trace_t trace ;
2010-07-11 12:13:40 +00:00
trace = World_Move ( w , ent - > v - > origin , ent - > v - > mins , ent - > v - > maxs , ent - > v - > origin , ( ( ent - > v - > solid = = SOLID_NOT | | ent - > v - > solid = = SOLID_TRIGGER ) ? MOVE_NOMONSTERS : 0 ) , ent ) ;
2004-08-23 00:15:46 +00:00
2014-08-17 02:27:54 +00:00
if ( trace . startsolid | | trace . allsolid )
2014-04-06 15:16:39 +00:00
return trace . ent ? trace . ent : w - > edicts ;
2004-08-23 00:15:46 +00:00
return NULL ;
}
2005-07-16 00:53:08 +00:00
qboolean Q1BSP_RecursiveHullCheck ( hull_t * hull , int num , float p1f , float p2f , vec3_t p1 , vec3_t p2 , trace_t * trace ) ;
2004-08-23 00:15:46 +00:00
//wrapper function. Rotates the start and end positions around the angles if needed.
2005-07-16 00:53:08 +00:00
//qboolean TransformedHullCheck (hull_t *hull, vec3_t start, vec3_t end, trace_t *trace, vec3_t angles)
2016-12-19 13:31:05 +00:00
qboolean World_TransformedTrace ( struct model_s * model , int hulloverride , framestate_t * framestate , vec3_t start , vec3_t end , vec3_t mins , vec3_t maxs , qboolean capsule , struct trace_s * trace , vec3_t origin , vec3_t angles , unsigned int hitcontentsmask )
2004-08-23 00:15:46 +00:00
{
vec3_t start_l , end_l ;
2010-08-28 17:14:38 +00:00
vec3_t axis [ 3 ] ;
2004-08-23 00:15:46 +00:00
qboolean result ;
2005-07-16 00:53:08 +00:00
memset ( trace , 0 , sizeof ( trace_t ) ) ;
trace - > fraction = 1 ;
2016-07-12 00:40:13 +00:00
trace - > allsolid = true ;
2005-07-16 00:53:08 +00:00
trace - > startsolid = false ;
trace - > inopen = true ; //probably wrong...
VectorCopy ( end , trace - > endpos ) ;
2011-05-20 04:10:46 +00:00
if ( IS_NAN ( end [ 0 ] ) | | IS_NAN ( end [ 1 ] ) | | IS_NAN ( end [ 2 ] ) )
{
Con_DPrintf ( " Nan in traceline \n " ) ;
return false ;
}
2004-08-23 00:15:46 +00:00
// don't rotate non bsp ents. Too small to bother.
2014-10-05 20:04:11 +00:00
if ( model & & model - > loadstate = = MLS_LOADED )
2004-08-23 00:15:46 +00:00
{
2010-08-28 17:14:38 +00:00
VectorSubtract ( start , origin , start_l ) ;
VectorSubtract ( end , origin , end_l ) ;
2005-07-16 00:53:08 +00:00
2010-08-28 17:14:38 +00:00
if ( angles [ 0 ] | | angles [ 1 ] | | angles [ 2 ] )
{
AngleVectors ( angles , axis [ 0 ] , axis [ 1 ] , axis [ 2 ] ) ;
VectorNegate ( axis [ 1 ] , axis [ 1 ] ) ;
2016-12-19 13:31:05 +00:00
result = model - > funcs . NativeTrace ( model , hulloverride , framestate , axis , start_l , end_l , mins , maxs , capsule , hitcontentsmask , trace ) ;
2005-07-16 00:53:08 +00:00
}
else
{
2016-12-19 13:31:05 +00:00
result = model - > funcs . NativeTrace ( model , hulloverride , framestate , NULL , start_l , end_l , mins , maxs , capsule , hitcontentsmask , trace ) ;
2005-07-16 00:53:08 +00:00
}
2010-08-28 17:14:38 +00:00
VectorAdd ( trace - > endpos , origin , trace - > endpos ) ;
2006-03-06 01:41:09 +00:00
}
2015-02-09 03:37:41 +00:00
else if ( hitcontentsmask & FTECONTENTS_BODY )
2006-03-06 01:41:09 +00:00
{
hull_t * hull = & box_hull ;
VectorSubtract ( start , origin , start_l ) ;
VectorSubtract ( end , origin , end_l ) ;
VectorCopy ( end_l , trace - > endpos ) ;
result = Q1BSP_RecursiveHullCheck ( hull , hull - > firstclipnode , 0 , 1 , start_l , end_l , trace ) ;
VectorAdd ( trace - > endpos , origin , trace - > endpos ) ;
2017-08-14 16:38:44 +00:00
trace - > contents = FTECONTENTS_BODY ;
2006-03-06 01:41:09 +00:00
}
2015-03-03 00:14:43 +00:00
else
result = false ;
2006-03-06 01:41:09 +00:00
return result ;
}
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = =
SV_ClipMoveToEntity
Handles selection or creation of a clipping hull , and offseting ( and
eventually rotation ) of the end points
= = = = = = = = = = = = = = = = = =
*/
2014-09-17 03:04:08 +00:00
static trace_t World_ClipMoveToEntity ( world_t * w , wedict_t * ent , vec3_t eorg , vec3_t start , vec3_t mins , vec3_t maxs , vec3_t end , int hullnum , qboolean hitmodel , qboolean capsule , unsigned int hitcontentsmask ) //hullnum overrides min/max for q1 style bsps
2004-08-23 00:15:46 +00:00
{
trace_t trace ;
2005-07-16 00:53:08 +00:00
model_t * model ;
2012-02-15 13:53:30 +00:00
int mdlidx = ent - > v - > modelindex ;
2016-12-19 13:31:05 +00:00
framestate_t framestate ;
2004-11-19 17:42:54 +00:00
2004-08-23 00:15:46 +00:00
// get the clipping hull
2013-12-29 22:48:28 +00:00
if ( ( ent - > v - > solid = = SOLID_BSP | | ent - > v - > solid = = SOLID_PORTAL ) & & mdlidx )
2005-07-16 00:53:08 +00:00
{
2012-02-15 13:53:30 +00:00
model = w - > Get_CModel ( w , mdlidx ) ;
2005-08-26 22:56:51 +00:00
if ( ! model | | ( model - > type ! = mod_brush & & model - > type ! = mod_heightmap ) )
2013-03-12 23:24:15 +00:00
{
// Host_Error("SOLID_BSP with non bsp model (classname: %s)", PR_GetString(w->progs, ent->v->classname));
model = NULL ;
}
2005-07-16 00:53:08 +00:00
}
else
2013-03-12 23:24:15 +00:00
model = NULL ;
2014-10-05 20:04:11 +00:00
if ( ! model | | model - > loadstate ! = MLS_LOADED )
2005-07-16 00:53:08 +00:00
{
vec3_t boxmins , boxmaxs ;
2014-09-17 03:04:08 +00:00
model = NULL ;
2005-07-16 00:53:08 +00:00
VectorSubtract ( ent - > v - > mins , maxs , boxmins ) ;
VectorSubtract ( ent - > v - > maxs , mins , boxmaxs ) ;
2017-08-14 16:38:44 +00:00
2018-02-04 13:16:25 +00:00
if ( hitcontentsmask & ( ( ent - > v - > solid = = SOLID_CORPSE & & w - > usesolidcorpse ) ? FTECONTENTS_CORPSE : FTECONTENTS_BODY ) )
2017-08-14 16:38:44 +00:00
hitcontentsmask = FTECONTENTS_CORPSE | FTECONTENTS_BODY ;
else
hitcontentsmask = 0 ;
2014-09-20 04:11:39 +00:00
// if (ent->xv->geomtype == GEOMTYPE_CAPSULE && !hitmodel)
// model = World_CapsuleForBox(boxmins, boxmaxs);
// else
2014-09-17 03:04:08 +00:00
World_HullForBox ( boxmins , boxmaxs ) ;
2005-07-16 00:53:08 +00:00
}
2004-08-23 00:15:46 +00:00
2016-12-19 13:31:05 +00:00
w - > Get_FrameState ( w , ent , & framestate ) ;
2004-08-23 00:15:46 +00:00
// trace a line through the apropriate clipping hull
2013-12-29 22:48:28 +00:00
if ( ent - > v - > solid = = SOLID_PORTAL )
{
//solid_portal cares only about origins and as such has no mins/max
2016-12-19 13:31:05 +00:00
World_TransformedTrace ( model , 0 , & framestate , start , end , vec3_origin , vec3_origin , capsule , & trace , eorg , ent - > v - > angles , hitcontentsmask ) ;
2014-06-16 16:21:28 +00:00
if ( trace . startsolid ) //portals should not block traces. this prevents infinite looping
2014-06-21 17:58:17 +00:00
trace . startsolid = false ;
2013-12-29 22:48:28 +00:00
hitmodel = false ;
}
else if ( ent - > v - > solid ! = SOLID_BSP )
2004-11-17 17:40:05 +00:00
{
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
ent - > v - > angles [ 0 ] * = r_meshpitch . value ; //carmack made bsp models rotate wrongly.
2016-12-19 13:31:05 +00:00
World_TransformedTrace ( model , hullnum , & framestate , start , end , mins , maxs , capsule , & trace , eorg , ent - > v - > angles , hitcontentsmask ) ;
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
ent - > v - > angles [ 0 ] * = r_meshpitch . value ;
2004-11-17 17:40:05 +00:00
}
else
{
2018-01-14 07:40:17 +00:00
if ( ent - > v - > skin < 0 )
{ //if forcedcontents is set, then ALL brushes in this model are forced to the specified contents value.
//we achive this by tracing against ALL then forcing it after.
int forcedcontents ;
switch ( ( int ) ent - > v - > skin )
{
2018-01-22 19:18:04 +00:00
case Q1CONTENTS_EMPTY : forcedcontents = FTECONTENTS_EMPTY ; break ;
case Q1CONTENTS_SOLID : forcedcontents = FTECONTENTS_SOLID ; break ;
case Q1CONTENTS_WATER : forcedcontents = FTECONTENTS_WATER ; break ;
case Q1CONTENTS_SLIME : forcedcontents = FTECONTENTS_SLIME ; break ;
case Q1CONTENTS_LAVA : forcedcontents = FTECONTENTS_LAVA ; break ;
case Q1CONTENTS_SKY : forcedcontents = FTECONTENTS_SKY ; break ;
case Q1CONTENTS_LADDER : forcedcontents = FTECONTENTS_LADDER ; break ;
default : forcedcontents = 0 ; break ;
2018-01-14 07:40:17 +00:00
}
if ( hitcontentsmask & forcedcontents )
{
World_TransformedTrace ( model , hullnum , & framestate , start , end , mins , maxs , capsule , & trace , eorg , ent - > v - > angles , ~ 0u ) ;
if ( trace . contents )
trace . contents = forcedcontents ;
}
else
{
memset ( & trace , 0 , sizeof ( trace_t ) ) ;
trace . fraction = 1 ;
trace . allsolid = true ;
trace . startsolid = false ;
trace . inopen = true ; //probably wrong...
VectorCopy ( end , trace . endpos ) ;
}
}
else
World_TransformedTrace ( model , hullnum , & framestate , start , end , mins , maxs , capsule , & trace , eorg , ent - > v - > angles , hitcontentsmask ) ;
2004-11-17 17:40:05 +00:00
}
2004-08-23 00:15:46 +00:00
2012-01-17 07:57:46 +00:00
// if using hitmodel, we know it hit the bounding box, so try a proper trace now.
2015-08-22 02:59:01 +00:00
if ( hitmodel & & ( trace . fraction ! = 1 | | trace . startsolid ) & & ! model )
2005-07-16 00:53:08 +00:00
{
2012-01-17 07:57:46 +00:00
//okay, we hit the bbox
2012-02-15 13:53:30 +00:00
model = w - > Get_CModel ( w , mdlidx ) ;
2005-07-16 00:53:08 +00:00
2014-10-05 20:04:11 +00:00
if ( model & & model - > funcs . NativeTrace & & model - > loadstate = = MLS_LOADED )
2012-01-17 07:57:46 +00:00
{
2014-09-17 03:04:08 +00:00
//do the second trace, using the actual mesh.
2016-12-19 13:31:05 +00:00
World_TransformedTrace ( model , hullnum , & framestate , start , end , mins , maxs , capsule , & trace , eorg , ent - > v - > angles , hitcontentsmask ) ;
2005-07-16 00:53:08 +00:00
}
}
2004-08-23 00:15:46 +00:00
// did we clip the move?
2017-07-28 01:49:25 +00:00
if ( trace . fraction < 1 | | trace . startsolid | | trace . allsolid )
2004-08-23 00:15:46 +00:00
trace . ent = ent ;
return trace ;
}
2017-08-29 02:29:06 +00:00
# define AREA_ALL 0
# define AREA_SOLID 1
# define AREA_TRIGGER 2
# ifdef USEAREAGRID
/*
= = = = = = = = = = = = = = = =
SV_AreaEdicts
= = = = = = = = = = = = = = = =
*/
int World_AreaEdicts ( world_t * w , vec3_t mins , vec3_t maxs , wedict_t * * list , int maxcount , int areatype )
2004-08-23 00:15:46 +00:00
{
2017-08-29 02:29:06 +00:00
wedict_t * check ;
areagridlink_t * start , * l ;
size_t count = 0 ;
int ming [ 2 ] , maxg [ 2 ] , g [ 2 ] , ga ;
CALCAREAGRIDBOUNDS ( w , mins , maxs ) ;
2004-08-23 00:15:46 +00:00
2017-08-29 02:29:06 +00:00
areagridsequence + + ;
2014-09-17 03:04:08 +00:00
2017-08-29 02:29:06 +00:00
//check ents that are just too large first
start = & w - > jumboarea ;
for ( l = ( areagridlink_t * ) start - > l . next ; l ! = start ; l = ( areagridlink_t * ) l - > l . next )
2005-08-03 23:14:59 +00:00
{
2017-08-29 02:29:06 +00:00
check = l - > ed ;
// if (check->gridareasequence == areagridsequence)
// continue;
check - > gridareasequence = areagridsequence ;
if ( areatype ! = AREA_ALL )
{
if ( check - > v - > solid = = SOLID_NOT )
continue ; // deactivated
if ( ( check - > v - > solid = = SOLID_TRIGGER ) ! = ( areatype = = AREA_TRIGGER ) )
continue ;
}
if ( check - > v - > absmin [ 0 ] > maxs [ 0 ]
| | check - > v - > absmin [ 1 ] > maxs [ 1 ]
| | check - > v - > absmin [ 2 ] > maxs [ 2 ]
| | check - > v - > absmax [ 0 ] < mins [ 0 ]
| | check - > v - > absmax [ 1 ] < mins [ 1 ]
| | check - > v - > absmax [ 2 ] < mins [ 2 ] )
continue ; // not touching
if ( count = = maxcount )
{
Con_Printf ( " World_AreaEdicts: MAXCOUNT \n " ) ;
return count ;
}
list [ count ] = check ;
count + + ;
2005-08-03 23:14:59 +00:00
}
2004-08-23 00:15:46 +00:00
2017-08-29 02:29:06 +00:00
//check the actual grid now.
for ( ga = 0 , g [ 0 ] = ming [ 0 ] ; g [ 0 ] < maxg [ 0 ] ; g [ 0 ] + + )
{
for ( g [ 1 ] = ming [ 1 ] ; g [ 1 ] < maxg [ 1 ] ; g [ 1 ] + + , ga + + )
{
start = & w - > gridareas [ g [ 0 ] + g [ 1 ] * w - > gridsize [ 0 ] ] ;
for ( l = ( areagridlink_t * ) start - > l . next ; l ! = start ; l = ( areagridlink_t * ) l - > l . next )
{
check = l - > ed ;
2004-08-23 00:15:46 +00:00
2017-08-29 02:29:06 +00:00
if ( check - > gridareasequence = = areagridsequence )
continue ;
check - > gridareasequence = areagridsequence ;
if ( areatype ! = AREA_ALL )
{
if ( check - > v - > solid = = SOLID_NOT )
continue ; // deactivated
2005-08-03 23:14:59 +00:00
2017-08-29 02:29:06 +00:00
if ( ( check - > v - > solid = = SOLID_TRIGGER ) ! = ( areatype = = AREA_TRIGGER ) )
continue ;
}
if ( check - > v - > absmin [ 0 ] > maxs [ 0 ]
| | check - > v - > absmin [ 1 ] > maxs [ 1 ]
| | check - > v - > absmin [ 2 ] > maxs [ 2 ]
| | check - > v - > absmax [ 0 ] < mins [ 0 ]
| | check - > v - > absmax [ 1 ] < mins [ 1 ]
| | check - > v - > absmax [ 2 ] < mins [ 2 ] )
continue ; // not touching
if ( count = = maxcount )
{
Con_Printf ( " World_AreaEdicts: MAXCOUNT \n " ) ;
return count ;
}
list [ count ] = check ;
count + + ;
}
}
}
return count ;
2004-08-23 00:15:46 +00:00
}
2017-08-29 02:29:06 +00:00
# else
2004-08-23 00:15:46 +00:00
float * area_mins , * area_maxs ;
2009-11-04 21:16:50 +00:00
wedict_t * * area_list ;
2004-08-23 00:15:46 +00:00
# ifdef Q2SERVER
q2edict_t * * area_q2list ;
# endif
int area_count , area_maxcount ;
int area_type ;
2009-11-04 21:16:50 +00:00
static void World_AreaEdicts_r ( areanode_t * node )
2004-08-23 00:15:46 +00:00
{
link_t * l , * next , * start ;
2009-11-04 21:16:50 +00:00
wedict_t * check ;
2004-08-23 00:15:46 +00:00
// touch linked edicts
2011-06-29 18:39:11 +00:00
start = & node - > edicts ;
2004-08-23 00:15:46 +00:00
for ( l = start - > next ; l ! = start ; l = next )
{
next = l - > next ;
check = EDICT_FROM_AREA ( l ) ;
2005-03-28 00:11:59 +00:00
if ( check - > v - > solid = = SOLID_NOT )
2004-08-23 00:15:46 +00:00
continue ; // deactivated
2011-06-29 18:39:11 +00:00
/*q2 still has solid/trigger lists, emulate that here*/
if ( ( check - > v - > solid = = SOLID_TRIGGER ) ! = ( area_type = = AREA_TRIGGER ) )
continue ;
2005-03-28 00:11:59 +00:00
if ( check - > v - > absmin [ 0 ] > area_maxs [ 0 ]
| | check - > v - > absmin [ 1 ] > area_maxs [ 1 ]
| | check - > v - > absmin [ 2 ] > area_maxs [ 2 ]
| | check - > v - > absmax [ 0 ] < area_mins [ 0 ]
| | check - > v - > absmax [ 1 ] < area_mins [ 1 ]
| | check - > v - > absmax [ 2 ] < area_mins [ 2 ] )
2004-08-23 00:15:46 +00:00
continue ; // not touching
if ( area_count = = area_maxcount )
{
Con_Printf ( " SV_AreaEdicts: MAXCOUNT \n " ) ;
return ;
}
area_list [ area_count ] = check ;
area_count + + ;
}
if ( node - > axis = = - 1 )
return ; // terminal node
// recurse down both sides
if ( area_maxs [ node - > axis ] > node - > dist )
2009-11-04 21:16:50 +00:00
World_AreaEdicts_r ( node - > children [ 0 ] ) ;
2004-08-23 00:15:46 +00:00
if ( area_mins [ node - > axis ] < node - > dist )
2009-11-04 21:16:50 +00:00
World_AreaEdicts_r ( node - > children [ 1 ] ) ;
2004-08-23 00:15:46 +00:00
}
/*
= = = = = = = = = = = = = = = =
SV_AreaEdicts
= = = = = = = = = = = = = = = =
*/
2017-08-29 02:29:06 +00:00
int World_AreaEdicts ( world_t * w , vec3_t mins , vec3_t maxs , wedict_t * * list , int maxcount , int areatype )
2004-08-23 00:15:46 +00:00
{
area_mins = mins ;
area_maxs = maxs ;
area_list = list ;
area_count = 0 ;
area_maxcount = maxcount ;
area_type = areatype ;
2009-11-04 21:16:50 +00:00
World_AreaEdicts_r ( w - > areanodes ) ;
2004-08-23 00:15:46 +00:00
return area_count ;
}
2017-08-29 02:29:06 +00:00
# endif
2004-08-23 00:15:46 +00:00
# ifdef Q2SERVER
2017-08-29 02:29:06 +00:00
float * area_mins , * area_maxs ;
q2edict_t * * area_q2list ;
int area_count , area_maxcount ;
int area_type ;
2009-11-04 21:16:50 +00:00
static void WorldQ2_AreaEdicts_r ( areanode_t * node )
2004-08-23 00:15:46 +00:00
{
link_t * l , * next , * start ;
q2edict_t * check ;
// touch linked edicts
2011-06-29 18:39:11 +00:00
start = & node - > edicts ;
2004-08-23 00:15:46 +00:00
for ( l = start - > next ; l ! = start ; l = next )
{
if ( ! l )
{
int i ;
added r_meshpitch cvar that allows for fixing the unfixable mesh pitch bug from vanilla... needs a better name... do note that this will break pretty much any mod, so this is really only for TCs designed to use it. Its likely that I missed places.
nqsv: added support for spectators with nq clients. the angles are a bit rough, but hey. need to do something about frags so nq clients know who's a spectator. use 'cmd observe' to get an nq client to spectate on an fte server (then attack/jump behave the same as in qw clients).
nqsv: rewrote EF_MUZZLEFLASH handling, so svc_muzzleflash is now translated properly to EF_MUZZLEFLASH, and vice versa. No more missing muzzleflashes!
added screenshot_cubemap, so you can actually pre-generate cubemaps with fte (which can be used for reflections or whatever).
misc fixes (server crash, a couple of other less important ones).
external files based on a model's name will now obey r_replacemodels properly, instead of needing to use foo.mdl_0.skin for foo.md3.
identify <playernum> should now use the correct masked ip, instead of abrubtly failing (reported by kt)
vid_toggle console command should now obey vid_width and vid_height when switching to fullscreen, but only if vid_fullscreen is actually set, which should make it seem better behaved (reported by kt).
qcc: cleaned up sym->symboldata[sym->ofs] to be more consistent at all stages.
qcc: typedef float vec4[4]; now works to define a float array with 4 elements (however, it will be passed by-value rather than by-reference).
qcc: cleaned up optional vs __out ordering issues.
qccgui: shift+f3 searches backwards
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5064 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-02-27 09:34:35 +00:00
World_ClearWorld ( & sv . world , false ) ;
2004-08-23 00:15:46 +00:00
check = ge - > edicts ;
2004-09-15 03:06:20 +00:00
for ( i = 0 ; i < ge - > num_edicts ; i + + , check = ( q2edict_t * ) ( ( char * ) check + ge - > edict_size ) )
2004-08-23 00:15:46 +00:00
memset ( & check - > area , 0 , sizeof ( check - > area ) ) ;
Con_Printf ( " SV_AreaEdicts: Bad links \n " ) ;
return ;
}
next = l - > next ;
check = Q2EDICT_FROM_AREA ( l ) ;
if ( check - > solid = = Q2SOLID_NOT )
continue ; // deactivated
2011-06-29 18:39:11 +00:00
/*q2 still has solid/trigger lists, emulate that here*/
if ( ( check - > solid = = Q2SOLID_TRIGGER ) ! = ( area_type = = AREA_TRIGGER ) )
continue ;
2004-08-23 00:15:46 +00:00
if ( check - > absmin [ 0 ] > area_maxs [ 0 ]
| | check - > absmin [ 1 ] > area_maxs [ 1 ]
| | check - > absmin [ 2 ] > area_maxs [ 2 ]
| | check - > absmax [ 0 ] < area_mins [ 0 ]
| | check - > absmax [ 1 ] < area_mins [ 1 ]
| | check - > absmax [ 2 ] < area_mins [ 2 ] )
continue ; // not touching
if ( area_count = = area_maxcount )
{
Con_Printf ( " SV_AreaEdicts: MAXCOUNT \n " ) ;
return ;
}
area_q2list [ area_count ] = check ;
area_count + + ;
}
if ( node - > axis = = - 1 )
return ; // terminal node
// recurse down both sides
if ( area_maxs [ node - > axis ] > node - > dist )
2009-11-04 21:16:50 +00:00
WorldQ2_AreaEdicts_r ( node - > children [ 0 ] ) ;
2004-08-23 00:15:46 +00:00
if ( area_mins [ node - > axis ] < node - > dist )
2009-11-04 21:16:50 +00:00
WorldQ2_AreaEdicts_r ( node - > children [ 1 ] ) ;
2004-08-23 00:15:46 +00:00
}
2009-11-04 21:16:50 +00:00
int VARGS WorldQ2_AreaEdicts ( world_t * w , vec3_t mins , vec3_t maxs , q2edict_t * * list ,
2004-08-23 00:15:46 +00:00
int maxcount , int areatype )
{
area_mins = mins ;
area_maxs = maxs ;
area_q2list = list ;
area_count = 0 ;
area_maxcount = maxcount ;
area_type = areatype ;
2009-11-04 21:16:50 +00:00
WorldQ2_AreaEdicts_r ( w - > areanodes ) ;
2004-08-23 00:15:46 +00:00
return area_count ;
}
# endif
/*
= = = = = = = = = = = = = = = =
SV_HeadnodeForEntity
Returns a headnode that can be used for testing or clipping an
object of mins / maxs size .
Offset is filled in to contain the adjustment that must be added to the
testing object ' s origin to get a point to use with the returned hull .
= = = = = = = = = = = = = = = =
*/
# ifdef Q2SERVER
2009-11-04 21:16:50 +00:00
static model_t * WorldQ2_ModelForEntity ( world_t * w , q2edict_t * ent )
2004-08-23 00:15:46 +00:00
{
model_t * model ;
// decide which clipping hull to use, based on the size
if ( ent - > solid = = Q2SOLID_BSP )
{ // explicit hulls in the BSP model
2011-10-27 16:16:29 +00:00
model = w - > Get_CModel ( w , ent - > s . modelindex ) ;
2004-08-23 00:15:46 +00:00
if ( ! model )
SV_Error ( " Q2SOLID_BSP with a non bsp model " ) ;
2014-10-05 20:04:11 +00:00
if ( model - > loadstate = = MLS_LOADED )
return model ;
2004-08-23 00:15:46 +00:00
}
// create a temp hull from bounding box sizes
2005-08-26 22:56:51 +00:00
return CM_TempBoxModel ( ent - > mins , ent - > maxs ) ;
2004-08-23 00:15:46 +00:00
}
# endif
# ifdef Q2SERVER
2012-01-17 07:57:46 +00:00
void WorldQ2_ClipMoveToEntities ( world_t * w , moveclip_t * clip )
2004-08-23 00:15:46 +00:00
{
int i , num ;
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
q2edict_t * touchlist [ MAX_Q2EDICTS ] , * touch ;
2004-08-23 00:15:46 +00:00
trace_t trace ;
2005-08-26 22:56:51 +00:00
model_t * model ;
2004-08-23 00:15:46 +00:00
float * angles ;
2009-11-04 21:16:50 +00:00
num = WorldQ2_AreaEdicts ( w , clip - > boxmins , clip - > boxmaxs , touchlist
------------------------------------------------------------------------
r4169 | acceptthis | 2013-01-17 08:55:12 +0000 (Thu, 17 Jan 2013) | 31 lines
removed MAX_VISEDICTS limit.
PEXT2_REPLACEMENTDELTAS tweaked, now has 4 million entity limit. still not enabled by default.
TE_BEAM now maps to a separate TEQW_BEAM to avoid conflicts with QW.
added android multitouch emulation for windows/rawinput (in_simulatemultitouch).
split topcolor/bottomcolor from scoreboard, for dp's colormap|1024 feature.
now using utf-8 for windows consoles.
qcc warnings/errors now give clickable console links for quick+easy editing.
disabled menutint when the currently active item changes contrast or gamma (for OneManClan).
Added support for drawfont/drawfontscale.
tweaked the qcvm a little to reduce the number of pointers.
.doll file loading. still experimental and will likely crash. requires csqc active, even if its a dummy progs. this will be fixed in time. Still other things that need cleaning up.
windows: gl_font "?" shows the standard windows font-selection dialog, and can be used to select windows fonts. not all work. and you probably don't want to use windings.
fixed splitscreen support when playing mvds. added mini-scoreboards to splitscreen.
editor/debugger now shows asm if there's no linenumber info. also, pressing f1 for help shows the shortcuts.
Added support for .framegroups files for psk(psa) and iqm formats.
True support for ezquake's colour codes. Mutually exclusive with background colours.
path command output slightly more readable.
added support for digest_hex (MD4, SHA1, CRC16).
skingroups now colourmap correctly.
Fix terrain colour hints, and litdata from the wrong bsp.
fix ftp dual-homed issue. support epsv command, and enable ipv6 (eprt still not supported).
remove d3d11 compilation from the makefile. the required headers are not provided by mingw, and are not available to the build bot, so don't bother.
fix v *= v.x and similar opcodes.
fteqcc: fixed support for áéÃóú type chars in names. utf-8 files now properly supported (even with the utf-8 bom/identifier). utf-16 also supported.
fteqcc: fixed '#if 1 == 3 && 4' parsing.
fteqcc: -Werror acts on the warning, rather than as a separate error. Line numbers are thus more readable.
fteqcc: copyright message now includes compile date instead.
fteqccgui: the treeview control is now coloured depending on whether there were warnings/errors in the last compile.
fteqccgui: the output window is now focused and scrolls down as compilation progresses.
pr_dumpplatform command dumps out some pragmas to convert more serious warnings to errors. This is to avoid the infamous 'fteqcc sucks cos my code sucks' issue.
rewrote prespawn/modelist/soundlist code. server tracks progress now.
------------------------------------------------------------------------
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4167 fc73d0e0-1445-4013-8a0c-d673dee63da5
2013-03-12 22:29:40 +00:00
, MAX_Q2EDICTS , AREA_SOLID ) ;
2004-08-23 00:15:46 +00:00
// be careful, it is possible to have an entity in this
// list removed before we get to it (killtriggered)
for ( i = 0 ; i < num ; i + + )
{
touch = touchlist [ i ] ;
if ( touch - > solid = = Q2SOLID_NOT )
continue ;
if ( touch = = clip - > q2passedict )
continue ;
if ( clip - > trace . allsolid )
return ;
if ( clip - > q2passedict )
{
if ( touch - > owner = = clip - > q2passedict )
continue ; // don't clip against own missiles
if ( clip - > q2passedict - > owner = = touch )
continue ; // don't clip against owner
}
if ( touch - > svflags & SVF_DEADMONSTER )
2012-01-17 07:57:46 +00:00
if ( ! ( clip - > hitcontentsmask & Q2CONTENTS_DEADMONSTER ) )
2004-08-23 00:15:46 +00:00
continue ;
// might intersect, so do an exact clip
2009-11-04 21:16:50 +00:00
model = WorldQ2_ModelForEntity ( w , touch ) ;
2004-08-23 00:15:46 +00:00
angles = touch - > s . angles ;
if ( touch - > solid ! = Q2SOLID_BSP )
angles = vec3_origin ; // boxes don't rotate
if ( touch - > svflags & SVF_MONSTER )
2015-02-09 03:37:41 +00:00
World_TransformedTrace ( model , 0 , 0 , clip - > start , clip - > end , clip - > mins2 , clip - > maxs2 , false , & trace , touch - > s . origin , angles , clip - > hitcontentsmask ) ;
2004-08-23 00:15:46 +00:00
else
2015-02-09 03:37:41 +00:00
World_TransformedTrace ( model , 0 , 0 , clip - > start , clip - > end , clip - > mins , clip - > maxs , false , & trace , touch - > s . origin , angles , clip - > hitcontentsmask ) ;
2004-08-23 00:15:46 +00:00
if ( trace . allsolid | | trace . startsolid | |
trace . fraction < clip - > trace . fraction )
{
trace . ent = ( edict_t * ) touch ;
if ( clip - > trace . startsolid )
{
clip - > trace = trace ;
clip - > trace . startsolid = true ;
}
else
clip - > trace = trace ;
}
else if ( trace . startsolid )
clip - > trace . startsolid = true ;
}
# undef ped
}
# endif
//===========================================================================
2014-06-16 16:21:28 +00:00
//a portal is flush with a world surface behind it.
//this causes problems. namely that we can't pass through the portal plane if the bsp behind it prevents out origin from getting through.
//so if the trace was clipped and ended infront of the portal, continue the trace to the edges of the portal cutout instead.
2014-06-21 17:58:17 +00:00
void World_PortalCSG ( wedict_t * portal , float * trmin , float * trmax , vec3_t start , vec3_t end , trace_t * trace )
2014-06-16 16:21:28 +00:00
{
vec4_t planes [ 6 ] ; //far, near, right, left, up, down
int plane ;
vec3_t worldpos ;
2014-06-25 03:53:11 +00:00
float bestfrac ;
int hitplane ;
2014-06-16 16:21:28 +00:00
float portalradius = portal - > v - > impulse ;
//only run this code if we impacted on the portal's parent.
if ( trace - > fraction = = 1 & & ! trace - > startsolid )
return ;
if ( ! portalradius )
return ;
if ( trace - > startsolid )
VectorCopy ( start , worldpos ) ; //make sure we use a sane valid position.
else
VectorCopy ( trace - > endpos , worldpos ) ;
//determine the csg area. normals should be facing in
AngleVectors ( portal - > v - > angles , planes [ 1 ] , planes [ 3 ] , planes [ 5 ] ) ;
VectorNegate ( planes [ 1 ] , planes [ 0 ] ) ;
VectorNegate ( planes [ 3 ] , planes [ 2 ] ) ;
VectorNegate ( planes [ 5 ] , planes [ 4 ] ) ;
portalradius / = 2 ;
2014-06-25 03:53:11 +00:00
planes [ 0 ] [ 3 ] = DotProduct ( portal - > v - > origin , planes [ 0 ] ) - ( 4.0 / 32 ) ;
planes [ 1 ] [ 3 ] = DotProduct ( portal - > v - > origin , planes [ 1 ] ) - ( 4.0 / 32 ) ; //an epsilon beyond the portal
2014-06-21 17:58:17 +00:00
planes [ 2 ] [ 3 ] = DotProduct ( portal - > v - > origin , planes [ 2 ] ) - portalradius ;
planes [ 3 ] [ 3 ] = DotProduct ( portal - > v - > origin , planes [ 3 ] ) - portalradius ;
planes [ 4 ] [ 3 ] = DotProduct ( portal - > v - > origin , planes [ 4 ] ) - portalradius ;
planes [ 5 ] [ 3 ] = DotProduct ( portal - > v - > origin , planes [ 5 ] ) - portalradius ;
2014-06-16 16:21:28 +00:00
//if we're actually inside the csg region
for ( plane = 0 ; plane < 6 ; plane + + )
{
2014-06-21 17:58:17 +00:00
vec3_t nearest ;
2014-06-16 16:21:28 +00:00
float d = DotProduct ( worldpos , planes [ plane ] ) ;
2014-06-21 17:58:17 +00:00
int k ;
for ( k = 0 ; k < 3 ; k + + )
nearest [ k ] = ( planes [ plane ] [ k ] > = 0 ) ? trmax [ k ] : trmin [ k ] ;
if ( ! plane ) //front plane gets further away with side
planes [ plane ] [ 3 ] - = DotProduct ( nearest , planes [ plane ] ) ;
else if ( plane > 1 ) //side planes get nearer with size
2014-06-25 03:53:11 +00:00
planes [ plane ] [ 3 ] + = 24 ; //DotProduct(nearest, planes[plane]);
2014-06-16 16:21:28 +00:00
if ( d - planes [ plane ] [ 3 ] > = 0 )
continue ; //endpos is inside
else
return ; //end is already outside
}
//yup, we're inside, the trace shouldn't end where it actually did
2014-06-25 03:53:11 +00:00
bestfrac = 1 ;
hitplane = - 1 ;
2014-06-16 16:21:28 +00:00
for ( plane = 0 ; plane < 6 ; plane + + )
{
float ds = DotProduct ( start , planes [ plane ] ) - planes [ plane ] [ 3 ] ;
float de = DotProduct ( end , planes [ plane ] ) - planes [ plane ] [ 3 ] ;
float frac ;
2014-06-21 17:58:17 +00:00
if ( ds > = 0 & & de < 0 )
2014-06-16 16:21:28 +00:00
{
2014-06-25 03:53:11 +00:00
frac = ( ds ) / ( ds - de ) ;
if ( frac < bestfrac )
2014-06-16 16:21:28 +00:00
{
if ( frac < 0 )
frac = 0 ;
2014-06-25 03:53:11 +00:00
bestfrac = frac ;
hitplane = plane ;
2014-06-16 16:21:28 +00:00
}
}
}
2014-06-25 03:53:11 +00:00
trace - > startsolid = trace - > allsolid = false ;
//if we cross the front of the portal, don't shorten the trace, that will artificially clip us
if ( hitplane = = 0 & & trace - > fraction > bestfrac )
return ;
//okay, elongate to clip to the portal hole properly.
trace - > fraction = bestfrac ;
VectorInterpolate ( start , bestfrac , end , trace - > endpos ) ;
if ( hitplane > = 0 )
{
VectorCopy ( planes [ hitplane ] , trace - > plane . normal ) ;
trace - > plane . dist = planes [ hitplane ] [ 3 ] ;
if ( hitplane = = 1 )
trace - > ent = portal ;
}
2014-06-16 16:21:28 +00:00
}
2005-10-01 03:09:17 +00:00
/*
= = = = = = = = = = = = = = = = = = = =
SV_ClipToEverything
like SV_ClipToLinks , but doesn ' t use the links part . This can be used for checking triggers , solid entities , not - solid entities .
Sounds pointless , I know .
= = = = = = = = = = = = = = = = = = = =
*/
2009-11-04 21:16:50 +00:00
static void World_ClipToEverything ( world_t * w , moveclip_t * clip )
2005-10-01 03:09:17 +00:00
{
int e ;
trace_t trace ;
2009-11-04 21:16:50 +00:00
wedict_t * touch ;
for ( e = 1 ; e < w - > num_edicts ; e + + )
2005-10-01 03:09:17 +00:00
{
2009-11-17 00:15:44 +00:00
touch = ( wedict_t * ) EDICT_NUM ( w - > progs , e ) ;
2005-10-01 03:09:17 +00:00
2016-07-21 19:27:59 +00:00
if ( ED_ISFREE ( touch ) )
continue ;
2005-10-01 03:09:17 +00:00
if ( touch - > v - > solid = = SOLID_NOT & & ! ( ( int ) touch - > v - > flags & FL_FINDABLE_NONSOLID ) )
continue ;
if ( touch - > v - > solid = = SOLID_TRIGGER & & ! ( ( int ) touch - > v - > flags & FL_FINDABLE_NONSOLID ) )
continue ;
if ( touch = = clip - > passedict )
continue ;
if ( clip - > type & MOVE_NOMONSTERS & & touch - > v - > solid ! = SOLID_BSP )
continue ;
if ( clip - > passedict )
{
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
if ( w - > usesolidcorpse )
{
// don't clip corpse against character
if ( clip - > passedict - > v - > solid = = SOLID_CORPSE & & ( touch - > v - > solid = = SOLID_SLIDEBOX | | touch - > v - > solid = = SOLID_CORPSE ) )
continue ;
// don't clip character against corpse
if ( clip - > passedict - > v - > solid = = SOLID_SLIDEBOX & & touch - > v - > solid = = SOLID_CORPSE )
continue ;
}
2007-09-02 19:55:17 +00:00
if ( ! ( ( int ) clip - > passedict - > xv - > dimension_hit & ( int ) touch - > xv - > dimension_solid ) )
2005-10-01 03:09:17 +00:00
continue ;
}
if ( clip - > boxmins [ 0 ] > touch - > v - > absmax [ 0 ]
| | clip - > boxmins [ 1 ] > touch - > v - > absmax [ 1 ]
| | clip - > boxmins [ 2 ] > touch - > v - > absmax [ 2 ]
| | clip - > boxmaxs [ 0 ] < touch - > v - > absmin [ 0 ]
| | clip - > boxmaxs [ 1 ] < touch - > v - > absmin [ 1 ]
| | clip - > boxmaxs [ 2 ] < touch - > v - > absmin [ 2 ] )
continue ;
if ( clip - > passedict & & clip - > passedict - > v - > size [ 0 ] & & ! touch - > v - > size [ 0 ] )
continue ; // points never interact
// might intersect, so do an exact clip
2014-06-16 16:21:28 +00:00
// if (clip->trace.allsolid)
// return;
2005-10-01 03:09:17 +00:00
if ( clip - > passedict )
{
2009-11-17 00:15:44 +00:00
if ( ( wedict_t * ) PROG_TO_EDICT ( w - > progs , touch - > v - > owner ) = = clip - > passedict )
2005-10-01 03:09:17 +00:00
continue ; // don't clip against own missiles
2009-11-17 00:15:44 +00:00
if ( ( wedict_t * ) PROG_TO_EDICT ( w - > progs , clip - > passedict - > v - > owner ) = = touch )
2005-10-01 03:09:17 +00:00
continue ; // don't clip against owner
}
2014-06-16 16:21:28 +00:00
if ( touch - > v - > solid = = SOLID_PORTAL )
{
//make sure we don't hit the world if we're inside the portal
2014-06-21 17:58:17 +00:00
World_PortalCSG ( touch , clip - > mins , clip - > maxs , clip - > start , clip - > end , & clip - > trace ) ;
2014-06-16 16:21:28 +00:00
}
2005-10-01 03:09:17 +00:00
if ( ( int ) touch - > v - > flags & FL_MONSTER )
2014-09-17 03:04:08 +00:00
trace = World_ClipMoveToEntity ( w , touch , touch - > v - > origin , clip - > start , clip - > mins2 , clip - > maxs2 , clip - > end , clip - > hullnum , clip - > type & MOVE_HITMODEL , clip - > capsule , clip - > hitcontentsmask ) ;
2005-10-01 03:09:17 +00:00
else
2014-09-17 03:04:08 +00:00
trace = World_ClipMoveToEntity ( w , touch , touch - > v - > origin , clip - > start , clip - > mins , clip - > maxs , clip - > end , clip - > hullnum , clip - > type & MOVE_HITMODEL , clip - > capsule , clip - > hitcontentsmask ) ;
2005-10-01 03:09:17 +00:00
if ( trace . allsolid | | trace . startsolid | |
trace . fraction < clip - > trace . fraction )
{
2011-09-03 03:49:43 +00:00
if ( clip - > type & MOVE_ENTCHAIN )
{
touch - > v - > chain = EDICT_TO_PROG ( w - > progs , clip - > trace . ent ? clip - > trace . ent : w - > edicts ) ;
clip - > trace . ent = touch ;
}
else
{
trace . ent = touch ;
clip - > trace = trace ;
}
2005-10-01 03:09:17 +00:00
}
}
}
2017-08-29 02:29:06 +00:00
# ifdef USEAREAGRID
2004-08-23 00:15:46 +00:00
2017-08-29 02:29:06 +00:00
void World_TouchAllLinks ( world_t * w , wedict_t * ent )
{
wedict_t * touchedicts [ 512 ] , * touch ;
int num ;
num = World_AreaEdicts ( w , ent - > v - > absmin , ent - > v - > absmax , touchedicts , countof ( touchedicts ) , AREA_TRIGGER ) ;
while ( num - - > 0 )
{
touch = touchedicts [ num ] ;
//make sure nothing moved it away
if ( ED_ISFREE ( touch ) )
continue ;
if ( ! touch - > v - > touch | | touch - > v - > solid ! = SOLID_TRIGGER )
continue ;
2018-02-11 05:37:11 +00:00
if ( touch = = ent )
continue ;
2017-08-29 02:29:06 +00:00
if ( ent - > v - > absmin [ 0 ] > touch - > v - > absmax [ 0 ]
| | ent - > v - > absmin [ 1 ] > touch - > v - > absmax [ 1 ]
| | ent - > v - > absmin [ 2 ] > touch - > v - > absmax [ 2 ]
| | ent - > v - > absmax [ 0 ] < touch - > v - > absmin [ 0 ]
| | ent - > v - > absmax [ 1 ] < touch - > v - > absmin [ 1 ]
| | ent - > v - > absmax [ 2 ] < touch - > v - > absmin [ 2 ] )
continue ;
if ( ! ( ( int ) ent - > xv - > dimension_solid & ( int ) touch - > xv - > dimension_hit ) ) //didn't change did it?...
continue ;
w - > Event_Touch ( w , touch , ent ) ;
if ( ED_ISFREE ( ent ) )
break ;
}
}
void World_UnlinkEdict ( wedict_t * ent )
{
size_t i ;
for ( i = 0 ; i < countof ( ent - > gridareas ) ; i + + )
{
if ( ! ent - > gridareas [ i ] . l . prev )
return ; // not linked in anywhere
RemoveLink ( & ent - > gridareas [ i ] . l ) ;
ent - > gridareas [ i ] . l . prev = ent - > gridareas [ i ] . l . next = NULL ;
}
}
static void World_ClipToLinks ( world_t * w , areagridlink_t * node , moveclip_t * clip )
2004-08-23 00:15:46 +00:00
{
link_t * l , * next ;
2009-11-04 21:16:50 +00:00
wedict_t * touch ;
2004-08-23 00:15:46 +00:00
trace_t trace ;
// touch linked edicts
2017-08-29 02:29:06 +00:00
for ( l = node - > l . next ; l ! = & node - > l ; l = next )
2004-08-23 00:15:46 +00:00
{
next = l - > next ;
2017-08-29 02:29:06 +00:00
touch = ( ( areagridlink_t * ) l ) - > ed ;
if ( touch - > gridareasequence = = areagridsequence )
continue ;
touch - > gridareasequence = areagridsequence ;
2005-03-28 00:11:59 +00:00
if ( touch - > v - > solid = = SOLID_NOT )
2004-08-23 00:15:46 +00:00
continue ;
if ( touch = = clip - > passedict )
continue ;
2011-06-29 18:39:11 +00:00
/*if its a trigger, we only clip against it if the flags are aligned*/
2005-03-28 00:11:59 +00:00
if ( touch - > v - > solid = = SOLID_TRIGGER | | touch - > v - > solid = = SOLID_LADDER )
2010-07-11 02:22:39 +00:00
{
2011-06-29 18:39:11 +00:00
if ( ! ( clip - > type & MOVE_TRIGGERS ) )
continue ;
if ( ! ( ( int ) touch - > v - > flags & FL_FINDABLE_NONSOLID ) )
continue ;
2010-07-11 02:22:39 +00:00
}
2004-08-23 00:15:46 +00:00
2009-11-04 21:16:50 +00:00
if ( clip - > type & MOVE_LAGGED )
{
//can't touch lagged ents - we do an explicit test for them later.
if ( touch - > entnum - 1 < w - > maxlagents )
if ( w - > lagents [ touch - > entnum - 1 ] . present )
continue ;
}
2014-01-13 02:42:25 +00:00
if ( ( clip - > type & MOVE_NOMONSTERS ) & & ( touch - > v - > solid ! = SOLID_BSP & & touch - > v - > solid ! = SOLID_PORTAL ) )
2004-08-23 00:15:46 +00:00
continue ;
2005-07-01 19:23:00 +00:00
if ( clip - > passedict )
{
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
if ( w - > usesolidcorpse )
{
2017-08-14 16:38:44 +00:00
# if 1
// if (!(clip->hitcontentsmask & ((touch->v->solid == SOLID_CORPSE)?FTECONTENTS_CORPSE:FTECONTENTS_BODY)))
// continue;
# else
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
// don't clip corpse against character
if ( clip - > passedict - > v - > solid = = SOLID_CORPSE & & ( touch - > v - > solid = = SOLID_SLIDEBOX | | touch - > v - > solid = = SOLID_CORPSE ) )
continue ;
// don't clip character against corpse
if ( clip - > passedict - > v - > solid = = SOLID_SLIDEBOX & & touch - > v - > solid = = SOLID_CORPSE )
continue ;
2017-08-14 16:38:44 +00:00
# endif
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
}
2007-09-02 19:55:17 +00:00
if ( ! ( ( int ) clip - > passedict - > xv - > dimension_hit & ( int ) touch - > xv - > dimension_solid ) )
2005-07-01 19:23:00 +00:00
continue ;
}
2004-11-23 15:13:32 +00:00
2005-03-28 00:11:59 +00:00
if ( clip - > boxmins [ 0 ] > touch - > v - > absmax [ 0 ]
| | clip - > boxmins [ 1 ] > touch - > v - > absmax [ 1 ]
| | clip - > boxmins [ 2 ] > touch - > v - > absmax [ 2 ]
| | clip - > boxmaxs [ 0 ] < touch - > v - > absmin [ 0 ]
| | clip - > boxmaxs [ 1 ] < touch - > v - > absmin [ 1 ]
| | clip - > boxmaxs [ 2 ] < touch - > v - > absmin [ 2 ] )
2004-08-23 00:15:46 +00:00
continue ;
2005-03-28 00:11:59 +00:00
if ( clip - > passedict & & clip - > passedict - > v - > size [ 0 ] & & ! touch - > v - > size [ 0 ] )
2004-08-23 00:15:46 +00:00
continue ; // points never interact
// might intersect, so do an exact clip
2013-10-08 14:28:11 +00:00
// if (clip->trace.allsolid)
// return;
2004-08-23 00:15:46 +00:00
if ( clip - > passedict )
{
2009-11-17 00:15:44 +00:00
if ( ( wedict_t * ) PROG_TO_EDICT ( w - > progs , touch - > v - > owner ) = = clip - > passedict )
2004-08-23 00:15:46 +00:00
continue ; // don't clip against own missiles
2009-11-17 00:15:44 +00:00
if ( ( wedict_t * ) PROG_TO_EDICT ( w - > progs , clip - > passedict - > v - > owner ) = = touch )
2004-08-23 00:15:46 +00:00
continue ; // don't clip against owner
}
2014-06-16 16:21:28 +00:00
if ( touch - > v - > solid = = SOLID_PORTAL )
{
//make sure we don't hit the world if we're inside the portal
2014-06-21 17:58:17 +00:00
World_PortalCSG ( touch , clip - > mins , clip - > maxs , clip - > start , clip - > end , & clip - > trace ) ;
2014-06-16 16:21:28 +00:00
}
2005-03-28 00:11:59 +00:00
if ( ( int ) touch - > v - > flags & FL_MONSTER )
2014-09-17 03:04:08 +00:00
trace = World_ClipMoveToEntity ( w , touch , touch - > v - > origin , clip - > start , clip - > mins2 , clip - > maxs2 , clip - > end , clip - > hullnum , clip - > type & MOVE_HITMODEL , clip - > capsule , clip - > hitcontentsmask ) ;
2004-08-23 00:15:46 +00:00
else
2014-09-17 03:04:08 +00:00
trace = World_ClipMoveToEntity ( w , touch , touch - > v - > origin , clip - > start , clip - > mins , clip - > maxs , clip - > end , clip - > hullnum , clip - > type & MOVE_HITMODEL , clip - > capsule , clip - > hitcontentsmask ) ;
2011-09-03 03:49:43 +00:00
2014-08-17 02:27:54 +00:00
if ( trace . fraction < clip - > trace . fraction )
2004-08-23 00:15:46 +00:00
{
2014-08-17 02:27:54 +00:00
//trace traveled less, but don't forget if we started in a solid.
trace . startsolid | = clip - > trace . startsolid ;
trace . allsolid | = clip - > trace . allsolid ;
2011-09-03 03:49:43 +00:00
if ( clip - > type & MOVE_ENTCHAIN )
{
touch - > v - > chain = EDICT_TO_PROG ( w - > progs , clip - > trace . ent ? clip - > trace . ent : w - > edicts ) ;
clip - > trace . ent = touch ;
}
else
{
2014-08-17 02:27:54 +00:00
if ( clip - > trace . startsolid & & ! trace . startsolid )
trace . ent = clip - > trace . ent ; //something else hit earlier, that one gets the trace entity, but not the fraction. yeah, combining traces like this was always going to be weird.
else
trace . ent = touch ;
2011-09-03 03:49:43 +00:00
clip - > trace = trace ;
}
2004-08-23 00:15:46 +00:00
}
2014-08-17 02:27:54 +00:00
else if ( trace . startsolid | | trace . allsolid )
{
//even if the trace traveled less, we still care if it was in a solid.
clip - > trace . startsolid | = trace . startsolid ;
clip - > trace . allsolid | = trace . allsolid ;
if ( ! clip - > trace . ent )
2018-01-14 07:40:17 +00:00
{
clip - > trace . contents = trace . contents ;
2014-08-17 02:27:54 +00:00
clip - > trace . ent = touch ;
2018-01-14 07:40:17 +00:00
}
2014-08-17 02:27:54 +00:00
}
2004-08-23 00:15:46 +00:00
}
2017-08-29 02:29:06 +00:00
}
static void World_ClipToAllLinks ( world_t * w , moveclip_t * clip )
{
int ming [ 2 ] , maxg [ 2 ] , g [ 2 ] ;
areagridsequence + + ;
World_ClipToLinks ( w , & w - > jumboarea , clip ) ;
2004-08-23 00:15:46 +00:00
2017-08-29 02:29:06 +00:00
CALCAREAGRIDBOUNDS ( w , clip - > boxmins , clip - > boxmaxs ) ;
for ( g [ 0 ] = ming [ 0 ] ; g [ 0 ] < maxg [ 0 ] ; g [ 0 ] + + )
for ( g [ 1 ] = ming [ 1 ] ; g [ 1 ] < maxg [ 1 ] ; g [ 1 ] + + )
{
World_ClipToLinks ( w , & w - > gridareas [ g [ 0 ] + g [ 1 ] * w - > gridsize [ 0 ] ] , clip ) ;
}
2004-08-23 00:15:46 +00:00
}
2017-08-29 02:29:06 +00:00
# else
/*
= = = = = = = = = = = = = = = = = = = =
SV_ClipToLinks
Mins and maxs enclose the entire area swept by the move
= = = = = = = = = = = = = = = = = = = =
*/
static void World_ClipToLinks ( world_t * w , areanode_t * node , moveclip_t * clip )
2004-08-23 00:15:46 +00:00
{
link_t * l , * next ;
2017-08-29 02:29:06 +00:00
wedict_t * touch ;
2004-08-23 00:15:46 +00:00
trace_t trace ;
// touch linked edicts
2011-06-29 18:39:11 +00:00
for ( l = node - > edicts . next ; l ! = & node - > edicts ; l = next )
2004-08-23 00:15:46 +00:00
{
next = l - > next ;
2017-08-29 02:29:06 +00:00
touch = EDICT_FROM_AREA ( l ) ;
if ( touch - > v - > solid = = SOLID_NOT )
2004-08-23 00:15:46 +00:00
continue ;
2017-08-29 02:29:06 +00:00
if ( touch = = clip - > passedict )
2004-08-23 00:15:46 +00:00
continue ;
2017-08-29 02:29:06 +00:00
/*if its a trigger, we only clip against it if the flags are aligned*/
if ( touch - > v - > solid = = SOLID_TRIGGER | | touch - > v - > solid = = SOLID_LADDER )
{
if ( ! ( clip - > type & MOVE_TRIGGERS ) )
continue ;
if ( ! ( ( int ) touch - > v - > flags & FL_FINDABLE_NONSOLID ) )
continue ;
}
if ( clip - > type & MOVE_LAGGED )
{
//can't touch lagged ents - we do an explicit test for them later.
if ( touch - > entnum - 1 < w - > maxlagents )
if ( w - > lagents [ touch - > entnum - 1 ] . present )
continue ;
}
if ( ( clip - > type & MOVE_NOMONSTERS ) & & ( touch - > v - > solid ! = SOLID_BSP & & touch - > v - > solid ! = SOLID_PORTAL ) )
2004-08-23 00:15:46 +00:00
continue ;
2017-08-29 02:29:06 +00:00
if ( clip - > passedict )
{
if ( w - > usesolidcorpse )
{
# if 1
// if (!(clip->hitcontentsmask & ((touch->v->solid == SOLID_CORPSE)?FTECONTENTS_CORPSE:FTECONTENTS_BODY)))
// continue;
# else
// don't clip corpse against character
if ( clip - > passedict - > v - > solid = = SOLID_CORPSE & & ( touch - > v - > solid = = SOLID_SLIDEBOX | | touch - > v - > solid = = SOLID_CORPSE ) )
continue ;
// don't clip character against corpse
if ( clip - > passedict - > v - > solid = = SOLID_SLIDEBOX & & touch - > v - > solid = = SOLID_CORPSE )
continue ;
# endif
}
if ( ! ( ( int ) clip - > passedict - > xv - > dimension_hit & ( int ) touch - > xv - > dimension_solid ) )
continue ;
}
if ( clip - > boxmins [ 0 ] > touch - > v - > absmax [ 0 ]
| | clip - > boxmins [ 1 ] > touch - > v - > absmax [ 1 ]
| | clip - > boxmins [ 2 ] > touch - > v - > absmax [ 2 ]
| | clip - > boxmaxs [ 0 ] < touch - > v - > absmin [ 0 ]
| | clip - > boxmaxs [ 1 ] < touch - > v - > absmin [ 1 ]
| | clip - > boxmaxs [ 2 ] < touch - > v - > absmin [ 2 ] )
2004-08-23 00:15:46 +00:00
continue ;
2017-08-29 02:29:06 +00:00
if ( clip - > passedict & & clip - > passedict - > v - > size [ 0 ] & & ! touch - > v - > size [ 0 ] )
2004-08-23 00:15:46 +00:00
continue ; // points never interact
// might intersect, so do an exact clip
2017-08-29 02:29:06 +00:00
// if (clip->trace.allsolid)
// return;
2004-08-23 00:15:46 +00:00
if ( clip - > passedict )
{
2017-08-29 02:29:06 +00:00
if ( ( wedict_t * ) PROG_TO_EDICT ( w - > progs , touch - > v - > owner ) = = clip - > passedict )
2004-08-23 00:15:46 +00:00
continue ; // don't clip against own missiles
2017-08-29 02:29:06 +00:00
if ( ( wedict_t * ) PROG_TO_EDICT ( w - > progs , clip - > passedict - > v - > owner ) = = touch )
2004-08-23 00:15:46 +00:00
continue ; // don't clip against owner
}
2017-08-29 02:29:06 +00:00
if ( touch - > v - > solid = = SOLID_PORTAL )
{
//make sure we don't hit the world if we're inside the portal
World_PortalCSG ( touch , clip - > mins , clip - > maxs , clip - > start , clip - > end , & clip - > trace ) ;
}
2005-07-16 00:53:08 +00:00
2017-08-29 02:29:06 +00:00
if ( ( int ) touch - > v - > flags & FL_MONSTER )
trace = World_ClipMoveToEntity ( w , touch , touch - > v - > origin , clip - > start , clip - > mins2 , clip - > maxs2 , clip - > end , clip - > hullnum , clip - > type & MOVE_HITMODEL , clip - > capsule , clip - > hitcontentsmask ) ;
else
trace = World_ClipMoveToEntity ( w , touch , touch - > v - > origin , clip - > start , clip - > mins , clip - > maxs , clip - > end , clip - > hullnum , clip - > type & MOVE_HITMODEL , clip - > capsule , clip - > hitcontentsmask ) ;
if ( trace . fraction < clip - > trace . fraction )
2004-08-23 00:15:46 +00:00
{
2017-08-29 02:29:06 +00:00
//trace traveled less, but don't forget if we started in a solid.
trace . startsolid | = clip - > trace . startsolid ;
trace . allsolid | = clip - > trace . allsolid ;
if ( clip - > type & MOVE_ENTCHAIN )
{
touch - > v - > chain = EDICT_TO_PROG ( w - > progs , clip - > trace . ent ? clip - > trace . ent : w - > edicts ) ;
clip - > trace . ent = touch ;
}
else
{
if ( clip - > trace . startsolid & & ! trace . startsolid )
trace . ent = clip - > trace . ent ; //something else hit earlier, that one gets the trace entity, but not the fraction. yeah, combining traces like this was always going to be weird.
else
trace . ent = touch ;
clip - > trace = trace ;
}
}
else if ( trace . startsolid | | trace . allsolid )
{
//even if the trace traveled less, we still care if it was in a solid.
clip - > trace . startsolid | = trace . startsolid ;
clip - > trace . allsolid | = trace . allsolid ;
if ( ! clip - > trace . ent )
clip - > trace . ent = touch ;
2004-08-23 00:15:46 +00:00
}
}
// recurse down both sides
if ( node - > axis = = - 1 )
return ;
if ( clip - > boxmaxs [ node - > axis ] > node - > dist )
2009-11-04 21:16:50 +00:00
World_ClipToLinks ( w , node - > children [ 0 ] , clip ) ;
2004-08-23 00:15:46 +00:00
if ( clip - > boxmins [ node - > axis ] < node - > dist )
2009-11-04 21:16:50 +00:00
World_ClipToLinks ( w , node - > children [ 1 ] , clip ) ;
2004-08-23 00:15:46 +00:00
}
# endif
/*
= = = = = = = = = = = = = = = = = =
SV_MoveBounds
= = = = = = = = = = = = = = = = = =
*/
2009-11-04 21:16:50 +00:00
static void World_MoveBounds ( vec3_t start , vec3_t mins , vec3_t maxs , vec3_t end , vec3_t boxmins , vec3_t boxmaxs )
2004-08-23 00:15:46 +00:00
{
#if 0
// debug to test against everything
boxmins [ 0 ] = boxmins [ 1 ] = boxmins [ 2 ] = - 9999 ;
boxmaxs [ 0 ] = boxmaxs [ 1 ] = boxmaxs [ 2 ] = 9999 ;
# else
int i ;
for ( i = 0 ; i < 3 ; i + + )
{
if ( end [ i ] > start [ i ] )
{
boxmins [ i ] = start [ i ] + mins [ i ] - 1 ;
boxmaxs [ i ] = end [ i ] + maxs [ i ] + 1 ;
}
else
{
boxmins [ i ] = end [ i ] + mins [ i ] - 1 ;
boxmaxs [ i ] = start [ i ] + maxs [ i ] + 1 ;
}
}
# endif
}
playdemo accepts https urls now. will start playing before the file has finished downloading, to avoid unnecessary delays.
reworked network addresses to separate address family and connection type. this should make banning people more reliable, as well as simplifying a whole load of logic (no need to check for ipv4 AND ipv6).
tcpconnect will keep trying to connect even if the connection wasn't instant, instead of giving up instantly.
rewrote tcp connections quite a bit. sv_port_tcp now handles qtv+qizmo+http+ws+rtcbroker+tls equivalents.
qtv_streamport is now a legacy cvar and now acts equivalently to sv_port_tcp (but still separate).
rewrote screenshot and video capture code to use strides. this solves image-is-upside down issues with vulkan.
ignore alt key in browser port. oh no! no more red text! oh no! no more alt-being-wrongly-down-and-being-unable-to-type-anything-without-forcing-alt-released!
reworked audio decoder interface. now has clearly defined success/unavailable/end-of-file results. this should solve a whole load of issues with audio streaming.
fixed various openal audio streaming issues too. openal also got some workarounds for emscripten's poor emulation.
fixed ogg decoder to retain sync properly if seeked.
updated menu_media a bit. now reads vorbis comments/id3v1 tags to get proper track names. also saves the playlist so you don't have to manually repopulate the list so it might actually be usable now (after how many years?)
r_stains now defaults to 0, and is no longer enabled by presets. use decals if you want that sort of thing.
added fs_noreexec cvar, so configs will not be reexeced on gamedir change. this also means defaults won't be reapplied, etc.
added 'nvvk' renderer on windows, using nvidia's vulkan-inside-opengl gl extension. mostly just to see how much slower it is.
fixed up the ftp server quite a lot. more complete, more compliant, and should do ipv6 properly to-boot. file transfers also threaded.
fixed potential crash inside runclientphys.
experimental sv_antilag=3 setting. totally untested. the aim is to avoid missing due to lagged knockbacks. may be expensive for the server.
browser port's websockets support fixed. experimental support for webrtc ('works for me', requires a broker server).
updated avplug(renamed to ffmpeg so people know what it is) to use ffmpeg 3.2.4 properly, with its new encoder api. should be much more robust... also added experimental audio decoder for game music etc (currently doesn't resample, so playback rates are screwed, disabled by cvar).
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5097 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-05-10 02:08:58 +00:00
# if !defined(CLIENTONLY)
qboolean SV_AntiKnockBack ( world_t * w , client_t * client )
{
int seq = client - > netchan . incoming_acknowledged ; //our outgoing sequence that was last acked (in qw, this matches the last known-good input frame)
client_frame_t * frame ;
edict_t * ent = client - > edict ;
if ( client - > protocol ! = SCP_QUAKEWORLD | | ! client - > frameunion . frames | | ! ent )
return false ; //FIXME: support nq protocols too
//reload player state from the journal (the input frame should already have been applied)
frame = & client - > frameunion . frames [ seq & UPDATE_MASK ] ;
VectorCopy ( frame - > pmorigin , pmove . origin ) ;
VectorCopy ( frame - > pmvelocity , pmove . velocity ) ;
pmove . pm_type = frame - > pmtype ;
pmove . jump_held = frame - > pmjumpheld ;
pmove . waterjumptime = frame - > pmwaterjumptime ;
pmove . onladder = frame - > pmonladder ;
//stuff not regenerated properly, shouldn't really be changing much or not very significant.
pmove . world = w ;
VectorCopy ( ent - > v - > mins , pmove . player_mins ) ;
VectorCopy ( ent - > v - > maxs , pmove . player_maxs ) ;
pmove . capsule = ( ent - > xv - > geomtype = = GEOMTYPE_CAPSULE ) ;
if ( ent - > xv - > gravitydir [ 2 ] | | ent - > xv - > gravitydir [ 1 ] | | ent - > xv - > gravitydir [ 0 ] )
VectorCopy ( ent - > xv - > gravitydir , pmove . gravitydir ) ;
else
VectorCopy ( w - > g . defaultgravitydir , pmove . gravitydir ) ;
//FIXME
VectorCopy ( ent - > v - > oldorigin , pmove . safeorigin ) ;
pmove . safeorigin_known = false ;
pmove . jump_msec = 0 ;
VectorClear ( pmove . basevelocity ) ;
//and apply each more recent frame
while ( + + seq < = client - > netchan . incoming_sequence )
{
if ( frame - > sequence ! = seq )
continue ; //FIXME: lost
pmove . sequence = seq ;
pmove . cmd = frame - > cmd ;
// pmove.angles;
// pmove.numphysent/physents;
PM_PlayerMove ( sv . gamespeed ) ;
}
return true ;
}
# endif
2004-08-23 00:15:46 +00:00
/*
= = = = = = = = = = = = = = = = = =
SV_Move
= = = = = = = = = = = = = = = = = =
*/
2009-11-04 21:16:50 +00:00
trace_t World_Move ( world_t * w , vec3_t start , vec3_t mins , vec3_t maxs , vec3_t end , int type , wedict_t * passedict )
2004-08-23 00:15:46 +00:00
{
moveclip_t clip ;
int i ;
int hullnum ;
memset ( & clip , 0 , sizeof ( moveclip_t ) ) ;
2016-07-12 00:40:13 +00:00
if ( passedict & & passedict - > xv - > hull & & ! ( type & MOVE_IGNOREHULL ) )
2007-09-02 19:55:17 +00:00
hullnum = passedict - > xv - > hull ;
2009-11-17 00:15:44 +00:00
# ifdef CLIENTONLY
else
hullnum = 0 ;
# else
2007-10-05 18:08:47 +00:00
else if ( sv_compatiblehulls . value )
2004-08-23 00:15:46 +00:00
hullnum = 0 ;
else
{
int diff ;
int best ;
hullnum = 0 ;
best = 8192 ;
//x/y pos/neg are assumed to be the same magnitute.
2004-11-19 17:42:54 +00:00
//z pos/height are assumed to be different from all the others.
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < MAX_MAP_HULLSM ; i + + )
{
2009-11-04 21:16:50 +00:00
if ( ! w - > worldmodel - > hulls [ i ] . available )
2004-08-23 00:15:46 +00:00
continue ;
# define sq(x) ((x)*(x))
2009-11-04 21:16:50 +00:00
diff = sq ( w - > worldmodel - > hulls [ i ] . clip_maxs [ 2 ] - maxs [ 2 ] ) +
sq ( w - > worldmodel - > hulls [ i ] . clip_mins [ 2 ] - mins [ 2 ] ) +
sq ( w - > worldmodel - > hulls [ i ] . clip_maxs [ 1 ] - maxs [ 1 ] ) +
sq ( w - > worldmodel - > hulls [ i ] . clip_mins [ 0 ] - mins [ 0 ] ) ;
2004-08-23 00:15:46 +00:00
if ( diff < best )
{
best = diff ;
hullnum = i ;
}
}
hullnum + + ;
}
2009-11-17 00:15:44 +00:00
# endif
2004-08-23 00:15:46 +00:00
playdemo accepts https urls now. will start playing before the file has finished downloading, to avoid unnecessary delays.
reworked network addresses to separate address family and connection type. this should make banning people more reliable, as well as simplifying a whole load of logic (no need to check for ipv4 AND ipv6).
tcpconnect will keep trying to connect even if the connection wasn't instant, instead of giving up instantly.
rewrote tcp connections quite a bit. sv_port_tcp now handles qtv+qizmo+http+ws+rtcbroker+tls equivalents.
qtv_streamport is now a legacy cvar and now acts equivalently to sv_port_tcp (but still separate).
rewrote screenshot and video capture code to use strides. this solves image-is-upside down issues with vulkan.
ignore alt key in browser port. oh no! no more red text! oh no! no more alt-being-wrongly-down-and-being-unable-to-type-anything-without-forcing-alt-released!
reworked audio decoder interface. now has clearly defined success/unavailable/end-of-file results. this should solve a whole load of issues with audio streaming.
fixed various openal audio streaming issues too. openal also got some workarounds for emscripten's poor emulation.
fixed ogg decoder to retain sync properly if seeked.
updated menu_media a bit. now reads vorbis comments/id3v1 tags to get proper track names. also saves the playlist so you don't have to manually repopulate the list so it might actually be usable now (after how many years?)
r_stains now defaults to 0, and is no longer enabled by presets. use decals if you want that sort of thing.
added fs_noreexec cvar, so configs will not be reexeced on gamedir change. this also means defaults won't be reapplied, etc.
added 'nvvk' renderer on windows, using nvidia's vulkan-inside-opengl gl extension. mostly just to see how much slower it is.
fixed up the ftp server quite a lot. more complete, more compliant, and should do ipv6 properly to-boot. file transfers also threaded.
fixed potential crash inside runclientphys.
experimental sv_antilag=3 setting. totally untested. the aim is to avoid missing due to lagged knockbacks. may be expensive for the server.
browser port's websockets support fixed. experimental support for webrtc ('works for me', requires a broker server).
updated avplug(renamed to ffmpeg so people know what it is) to use ffmpeg 3.2.4 properly, with its new encoder api. should be much more robust... also added experimental audio decoder for game music etc (currently doesn't resample, so playback rates are screwed, disabled by cvar).
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5097 fc73d0e0-1445-4013-8a0c-d673dee63da5
2017-05-10 02:08:58 +00:00
# if !defined(CLIENTONLY)
//figure out where the firing player was, and re-run their input frames to calculate their position without any velocity/knockback changes.
//then update the start position to compensate.
if ( ( clip . type & MOVE_LAGGED ) & & w = = & sv . world & & passedict - > entnum & & passedict - > entnum < = sv . allocated_client_slots & & sv_antilag . ival = = 3 )
{
vec3_t nudge ;
if ( SV_AntiKnockBack ( w , & svs . clients [ passedict - > entnum - 1 ] ) )
{
VectorSubtract ( pmove . origin , passedict - > v - > origin , nudge ) ;
VectorAdd ( start , nudge , start ) ;
VectorAdd ( end , nudge , end ) ;
}
}
# endif
2016-07-12 00:40:13 +00:00
if ( passedict - > xv - > hitcontentsmaski )
clip . hitcontentsmask = passedict - > xv - > hitcontentsmaski ;
2017-08-14 16:38:44 +00:00
# ifndef NOLEGACY
else if ( passedict - > xv - > dphitcontentsmask )
{
unsigned int nm = 0 , fl = passedict - > xv - > dphitcontentsmask ;
if ( fl & DPCONTENTS_SOLID )
nm | = FTECONTENTS_SOLID ;
if ( fl & DPCONTENTS_WATER )
nm | = FTECONTENTS_WATER ;
if ( fl & DPCONTENTS_SLIME )
nm | = FTECONTENTS_SLIME ;
if ( fl & DPCONTENTS_LAVA )
nm | = FTECONTENTS_LAVA ;
if ( fl & DPCONTENTS_SKY )
nm | = FTECONTENTS_SKY ;
if ( fl & DPCONTENTS_BODY )
nm | = FTECONTENTS_BODY ;
if ( fl & DPCONTENTS_CORPSE )
nm | = FTECONTENTS_CORPSE ;
if ( fl & DPCONTENTS_NODROP )
nm | = Q3CONTENTS_NODROP ;
if ( fl & DPCONTENTS_PLAYERCLIP )
nm | = FTECONTENTS_PLAYERCLIP ;
if ( fl & DPCONTENTS_MONSTERCLIP )
nm | = FTECONTENTS_MONSTERCLIP ;
if ( fl & DPCONTENTS_DONOTENTER )
nm | = Q3CONTENTS_DONOTENTER ;
if ( fl & DPCONTENTS_BOTCLIP )
nm | = Q3CONTENTS_BOTCLIP ;
// if (fl & DPCONTENTS_OPAQUE)
// nm |= DPCONTENTS_OPAQUE;
clip . hitcontentsmask = nm ;
}
# endif
2016-07-12 00:40:13 +00:00
/*#ifndef NOLEGACY
else if ( passedict - > xv - > hitcontentsmask )
2012-07-05 19:42:36 +00:00
clip . hitcontentsmask = passedict - > xv - > hitcontentsmask ;
2016-07-12 00:40:13 +00:00
# endif* /
2017-08-14 16:38:44 +00:00
else if ( passedict - > v - > solid = = SOLID_SLIDEBOX )
{
if ( ( int ) passedict - > v - > flags & FL_MONSTER )
clip . hitcontentsmask = FTECONTENTS_SOLID | Q2CONTENTS_WINDOW | FTECONTENTS_BODY | FTECONTENTS_MONSTERCLIP ; /*solid only to world*/
else if ( maxs [ 0 ] - mins [ 0 ] > 0 )
clip . hitcontentsmask = FTECONTENTS_SOLID | Q2CONTENTS_WINDOW | FTECONTENTS_BODY | FTECONTENTS_PLAYERCLIP ; /*impacts playerclip*/
else
clip . hitcontentsmask = FTECONTENTS_SOLID | Q2CONTENTS_WINDOW | FTECONTENTS_BODY ; //slidebox passes through corpses
}
else if ( passedict - > v - > solid = = SOLID_CORPSE )
clip . hitcontentsmask = FTECONTENTS_SOLID | Q2CONTENTS_WINDOW | FTECONTENTS_BODY ; //corpses ignore corpses
else if ( passedict - > v - > solid = = SOLID_TRIGGER )
clip . hitcontentsmask = FTECONTENTS_SOLID | Q2CONTENTS_WINDOW | FTECONTENTS_BODY ; //triggers ignore corpses too, apparently
2012-01-17 07:57:46 +00:00
else
2017-08-14 16:38:44 +00:00
clip . hitcontentsmask = FTECONTENTS_SOLID | Q2CONTENTS_WINDOW | FTECONTENTS_BODY | FTECONTENTS_CORPSE ; //regular projectiles.
2014-09-17 03:04:08 +00:00
clip . capsule = ( passedict - > xv - > geomtype = = GEOMTYPE_CAPSULE ) ;
2012-01-17 07:57:46 +00:00
2016-07-15 12:26:24 +00:00
if ( type & MOVE_OTHERONLY )
2013-12-08 20:06:55 +00:00
{
2016-07-15 12:26:24 +00:00
wedict_t * other = WEDICT_NUM ( w - > progs , * w - > g . other ) ;
return World_ClipMoveToEntity ( w , other , other - > v - > origin , start , mins , maxs , end , hullnum , type & MOVE_HITMODEL , clip . capsule , clip . hitcontentsmask ) ;
2013-12-08 20:06:55 +00:00
}
2004-08-23 00:15:46 +00:00
// clip to world
2014-09-17 03:04:08 +00:00
clip . trace = World_ClipMoveToEntity ( w , w - > edicts , w - > edicts - > v - > origin , start , mins , maxs , end , hullnum , false , clip . capsule , clip . hitcontentsmask ) ;
2004-08-23 00:15:46 +00:00
clip . start = start ;
clip . end = end ;
clip . mins = mins ;
clip . maxs = maxs ;
2005-07-16 17:04:36 +00:00
clip . type = type ;
2004-08-23 00:15:46 +00:00
clip . passedict = passedict ;
2014-04-06 15:16:39 +00:00
clip . hullnum = 0 ; //hullnum; //BUG: hexen2's SV_ClipMoveToEntity's move_ent argument is set inconsistantly. This has the effect that the SOLID_BSP's .hull field is used instead of the SOLID_BBOX entity. We can't fix this because hexen2 depends upon it - this is the 'tibet5' bug.
2004-08-23 00:15:46 +00:00
# ifdef Q2SERVER
clip . q2passedict = NULL ;
# endif
if ( type & MOVE_MISSILE )
{
2017-08-14 16:38:44 +00:00
if ( type & MOVE_NOMONSTERS )
return clip . trace ; //not sure why you'd really want this, but for the sake of dp compat...
2004-08-23 00:15:46 +00:00
for ( i = 0 ; i < 3 ; i + + )
{
clip . mins2 [ i ] = - 15 ;
clip . maxs2 [ i ] = 15 ;
}
}
else
{
VectorCopy ( mins , clip . mins2 ) ;
VectorCopy ( maxs , clip . maxs2 ) ;
}
// create the bounding box of the entire move
2009-11-04 21:16:50 +00:00
World_MoveBounds ( start , clip . mins2 , clip . maxs2 , end , clip . boxmins , clip . boxmaxs ) ;
2004-08-23 00:15:46 +00:00
// clip to entities
2005-10-01 03:09:17 +00:00
if ( clip . type & MOVE_EVERYTHING )
2009-11-04 21:16:50 +00:00
World_ClipToEverything ( w , & clip ) ;
2004-08-23 00:15:46 +00:00
else
2009-11-04 21:16:50 +00:00
{
if ( clip . type & MOVE_LAGGED )
{
clip . type & = ~ MOVE_LAGGED ;
2009-11-17 00:15:44 +00:00
# ifndef CLIENTONLY
if ( w = = & sv . world )
2009-11-04 21:16:50 +00:00
{
2011-04-25 03:25:22 +00:00
if ( passedict - > entnum & & passedict - > entnum < = sv . allocated_client_slots )
2009-11-04 21:16:50 +00:00
{
clip . type | = MOVE_LAGGED ;
2009-11-17 00:15:44 +00:00
w - > lagents = svs . clients [ passedict - > entnum - 1 ] . laggedents ;
w - > maxlagents = svs . clients [ passedict - > entnum - 1 ] . laggedents_count ;
w - > lagentsfrac = svs . clients [ passedict - > entnum - 1 ] . laggedents_frac ;
}
else if ( passedict - > v - > owner )
{
2011-04-25 03:25:22 +00:00
if ( passedict - > v - > owner & & passedict - > v - > owner < = sv . allocated_client_slots )
2009-11-17 00:15:44 +00:00
{
clip . type | = MOVE_LAGGED ;
w - > lagents = svs . clients [ passedict - > v - > owner - 1 ] . laggedents ;
w - > maxlagents = svs . clients [ passedict - > v - > owner - 1 ] . laggedents_count ;
w - > lagentsfrac = svs . clients [ passedict - > v - > owner - 1 ] . laggedents_frac ;
}
2009-11-04 21:16:50 +00:00
}
}
2009-11-17 00:15:44 +00:00
# endif
2009-11-04 21:16:50 +00:00
}
if ( clip . type & MOVE_LAGGED )
{
trace_t trace ;
wedict_t * touch ;
2009-11-13 16:54:21 +00:00
vec3_t lp ;
2009-11-04 21:16:50 +00:00
2017-08-29 02:29:06 +00:00
# ifdef USEAREAGRID
World_ClipToAllLinks ( w , & clip ) ;
# else
World_ClipToLinks ( w , w - > areanodes , & clip ) ;
# endif
2009-11-04 21:16:50 +00:00
for ( i = 0 ; i < w - > maxlagents ; i + + )
{
if ( ! w - > lagents [ i ] . present )
continue ;
if ( clip . trace . allsolid )
break ;
touch = ( wedict_t * ) EDICT_NUM ( w - > progs , i + 1 ) ;
if ( touch - > v - > solid = = SOLID_NOT )
continue ;
if ( touch = = clip . passedict )
continue ;
if ( touch - > v - > solid = = SOLID_TRIGGER | | touch - > v - > solid = = SOLID_LADDER )
2015-10-27 15:20:15 +00:00
{
if ( ! ( clip . type & MOVE_TRIGGERS ) )
continue ;
if ( ! ( ( int ) touch - > v - > flags & FL_FINDABLE_NONSOLID ) )
continue ;
}
2009-11-04 21:16:50 +00:00
if ( clip . type & MOVE_NOMONSTERS & & touch - > v - > solid ! = SOLID_BSP )
continue ;
if ( clip . passedict )
{
Fixes, workarounds, and breakages. Hexen2 should work much better (-hexen2 says no mission pack, -portals says h2mp). Started working on splitting bigcoords per client, far too much work still to go on that. Removed gl_ztrick entirely. Enabled csprogs download by default. Added client support for fitzquake's 666 protocol, needs testing, some cleanup for dp protocols too, no server support, couldn't selectively enable it anyway. Now attempting to cache shadow meshes for explosions and stuff. Played with lightmaps a little, should potentially run a little faster on certain (intel?) cards. Tweeked npfte a little to try to avoid deadlocks and crashes. Fixed sky worldspawn parsing. Added h2mp's model format. Fixed baseline issue in q2 client, made servers generate q2 baselines. MOVETYPE_PUSH will not rotate extra if rotation is forced. Made status command show allowed client types. Changed lighting on weapons - should now be shaded.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3572 fc73d0e0-1445-4013-8a0c-d673dee63da5
2010-08-11 03:36:31 +00:00
if ( w - > usesolidcorpse )
{
// don't clip corpse against character
if ( clip . passedict - > v - > solid = = SOLID_CORPSE & & ( touch - > v - > solid = = SOLID_SLIDEBOX | | touch - > v - > solid = = SOLID_CORPSE ) )
continue ;
// don't clip character against corpse
if ( clip . passedict - > v - > solid = = SOLID_SLIDEBOX & & touch - > v - > solid = = SOLID_CORPSE )
continue ;
}
2009-11-04 21:16:50 +00:00
if ( ! ( ( int ) clip . passedict - > xv - > dimension_hit & ( int ) touch - > xv - > dimension_solid ) )
continue ;
}
2009-11-13 16:54:21 +00:00
VectorInterpolate ( touch - > v - > origin , w - > lagentsfrac , w - > lagents [ i ] . laggedpos , lp ) ;
if ( clip . boxmins [ 0 ] > lp [ 0 ] + touch - > v - > maxs [ 0 ]
| | clip . boxmins [ 1 ] > lp [ 1 ] + touch - > v - > maxs [ 1 ]
| | clip . boxmins [ 2 ] > lp [ 2 ] + touch - > v - > maxs [ 2 ]
| | clip . boxmaxs [ 0 ] < lp [ 0 ] + touch - > v - > mins [ 0 ]
| | clip . boxmaxs [ 1 ] < lp [ 1 ] + touch - > v - > mins [ 1 ]
| | clip . boxmaxs [ 2 ] < lp [ 2 ] + touch - > v - > mins [ 2 ] )
2009-11-04 21:16:50 +00:00
continue ;
if ( clip . passedict & & clip . passedict - > v - > size [ 0 ] & & ! touch - > v - > size [ 0 ] )
continue ; // points never interact
if ( clip . passedict )
{
2009-11-17 00:15:44 +00:00
if ( ( wedict_t * ) PROG_TO_EDICT ( w - > progs , touch - > v - > owner ) = = clip . passedict )
2009-11-04 21:16:50 +00:00
continue ; // don't clip against own missiles
2009-11-17 00:15:44 +00:00
if ( ( wedict_t * ) PROG_TO_EDICT ( w - > progs , clip . passedict - > v - > owner ) = = touch )
2009-11-04 21:16:50 +00:00
continue ; // don't clip against owner
}
2014-09-17 03:04:08 +00:00
trace = World_ClipMoveToEntity ( w , touch , lp , clip . start , clip . mins , clip . maxs , clip . end , clip . hullnum , clip . type & MOVE_HITMODEL , clip . capsule , clip . hitcontentsmask ) ;
2009-11-04 21:16:50 +00:00
if ( trace . allsolid | | trace . startsolid | | trace . fraction < clip . trace . fraction )
{
2011-09-03 03:49:43 +00:00
if ( clip . type & MOVE_ENTCHAIN )
{
touch - > v - > chain = EDICT_TO_PROG ( w - > progs , clip . trace . ent ? clip . trace . ent : w - > edicts ) ;
clip . trace . ent = touch ;
}
else
{
trace . ent = touch ;
clip . trace = trace ;
}
2009-11-04 21:16:50 +00:00
}
}
}
else
2017-08-29 02:29:06 +00:00
{
# ifdef USEAREAGRID
World_ClipToAllLinks ( w , & clip ) ;
# else
2009-11-04 21:16:50 +00:00
World_ClipToLinks ( w , w - > areanodes , & clip ) ;
2017-08-29 02:29:06 +00:00
# endif
}
2014-07-12 06:56:17 +00:00
World_ClipToLinks ( w , & w - > portallist , & clip ) ;
2009-11-04 21:16:50 +00:00
}
2004-08-23 00:15:46 +00:00
2010-08-18 22:56:33 +00:00
// if (clip.trace.startsolid)
// clip.trace.fraction = 0;
2004-12-08 04:14:52 +00:00
2017-08-14 16:38:44 +00:00
// if (!clip.trace.ent)
// return clip.trace;
2005-08-26 22:56:51 +00:00
2004-08-23 00:15:46 +00:00
return clip . trace ;
}
# ifdef Q2SERVER
2012-01-17 07:57:46 +00:00
trace_t WorldQ2_Move ( world_t * w , vec3_t start , vec3_t mins , vec3_t maxs , vec3_t end , int hitcontentsmask , q2edict_t * passedict )
2004-08-23 00:15:46 +00:00
{
moveclip_t clip ;
memset ( & clip , 0 , sizeof ( moveclip_t ) ) ;
// clip to world
2017-01-29 13:10:53 +00:00
w - > worldmodel - > funcs . NativeTrace ( w - > worldmodel , 0 , NULLFRAMESTATE , NULL , start , end , mins , maxs , false , hitcontentsmask , & clip . trace ) ;
2009-11-04 21:16:50 +00:00
clip . trace . ent = ge - > edicts ;
2004-08-23 00:15:46 +00:00
if ( clip . trace . fraction = = 0 )
return clip . trace ;
clip . start = start ;
clip . end = end ;
clip . mins = mins ;
clip . maxs = maxs ;
2012-01-17 07:57:46 +00:00
clip . type = MOVE_NORMAL ;
clip . hitcontentsmask = hitcontentsmask ;
2004-08-23 00:15:46 +00:00
clip . passedict = NULL ;
clip . q2passedict = passedict ;
VectorCopy ( mins , clip . mins2 ) ;
VectorCopy ( maxs , clip . maxs2 ) ;
// create the bounding box of the entire move
2015-02-09 03:37:41 +00:00
//FIXME: should we use clip.trace.endpos here?
2009-11-04 21:16:50 +00:00
World_MoveBounds ( start , clip . mins2 , clip . maxs2 , end , clip . boxmins , clip . boxmaxs ) ;
2004-08-23 00:15:46 +00:00
// clip to entities
2017-08-29 02:29:06 +00:00
WorldQ2_ClipMoveToEntities ( w , & clip ) ;
2004-08-23 00:15:46 +00:00
return clip . trace ;
}
# endif
2015-02-02 08:01:53 +00:00
static void ( QDECL * world_current_physics_engine ) ( world_t * world ) ;
qboolean QDECL World_RegisterPhysicsEngine ( const char * enginename , void ( QDECL * startupfunc ) ( world_t * world ) )
{
if ( world_current_physics_engine )
return false ; //no thanks, we already have one.
world_current_physics_engine = startupfunc ;
return true ;
}
2015-10-11 11:34:58 +00:00
void World_RBE_Shutdown ( world_t * world )
2015-02-02 08:01:53 +00:00
{
2016-07-12 00:40:13 +00:00
# ifdef USERBE
2015-02-02 08:01:53 +00:00
unsigned int u ;
wedict_t * ed ;
if ( ! world - > rbe )
return ;
2015-06-14 08:16:15 +00:00
if ( world - > progs )
2015-02-02 08:01:53 +00:00
{
2015-06-14 08:16:15 +00:00
for ( u = 0 ; u < world - > num_edicts ; u + + )
{
ed = WEDICT_NUM ( world - > progs , u ) ;
world - > rbe - > RemoveJointFromEntity ( world , ed ) ;
world - > rbe - > RemoveFromEntity ( world , ed ) ;
}
2015-02-02 08:01:53 +00:00
}
world - > rbe - > End ( world ) ;
2017-04-18 11:12:17 +00:00
world - > rbe = NULL ;
2016-07-12 00:40:13 +00:00
# endif
2015-02-02 08:01:53 +00:00
}
void QDECL World_UnregisterPhysicsEngine ( const char * enginename )
{
# ifdef RAGDOLL
2016-07-21 19:27:59 +00:00
rag_uninstanciateall ( ) ;
2015-02-02 08:01:53 +00:00
# endif
# if defined(CSQC_DAT) && !defined(SERVERONLY)
{
extern world_t csqc_world ;
2015-10-11 11:34:58 +00:00
World_RBE_Shutdown ( & csqc_world ) ;
2015-02-02 08:01:53 +00:00
}
# endif
# if !defined(CLIENTONLY)
2015-10-11 11:34:58 +00:00
World_RBE_Shutdown ( & sv . world ) ;
2015-02-02 08:01:53 +00:00
# endif
world_current_physics_engine = NULL ;
}
void World_RBE_Start ( world_t * world )
{
if ( world_current_physics_engine )
2015-10-11 11:34:58 +00:00
{
if ( world - > worldmodel )
world_current_physics_engine ( world ) ;
}
2015-02-02 08:01:53 +00:00
}
2015-06-14 08:16:15 +00:00
void World_Destroy ( world_t * world )
{
2015-10-11 11:34:58 +00:00
World_RBE_Shutdown ( world ) ;
2015-06-14 08:16:15 +00:00
2017-08-29 02:29:06 +00:00
# ifdef USEAREAGRID
Z_Free ( world - > gridareas ) ;
# else
2015-06-14 08:16:15 +00:00
Z_Free ( world - > areanodes ) ;
world - > areanodes = NULL ;
world - > areanodedepth = 0 ;
2017-08-29 02:29:06 +00:00
# endif
2015-06-14 08:16:15 +00:00
memset ( world , 0 , sizeof ( * world ) ) ;
}
2015-02-02 08:01:53 +00:00
# ifdef USERBE
static qboolean GenerateCollisionMesh_BSP ( world_t * world , model_t * mod , wedict_t * ed , vec3_t geomcenter )
{
unsigned int sno ;
msurface_t * surf ;
mesh_t * mesh ;
unsigned int numverts ;
unsigned int numindexes , i ;
2016-01-18 05:22:07 +00:00
int * ptr_elements ;
float * ptr_verts ;
2015-02-02 08:01:53 +00:00
numverts = 0 ;
numindexes = 0 ;
for ( sno = 0 ; sno < mod - > nummodelsurfaces ; sno + + )
{
surf = & mod - > surfaces [ sno + mod - > firstmodelsurface ] ;
if ( surf - > flags & ( SURF_DRAWSKY | SURF_DRAWTURB ) )
continue ;
if ( surf - > mesh )
{
mesh = surf - > mesh ;
numverts + = mesh - > numvertexes ;
numindexes + = mesh - > numindexes ;
}
else
{
numverts + = surf - > numedges ;
numindexes + = ( surf - > numedges - 2 ) * 3 ;
}
}
if ( ! numindexes )
{
Con_DPrintf ( " entity %i (classname %s) has no geometry \n " , NUM_FOR_EDICT ( world - > progs , ( edict_t * ) ed ) , PR_GetString ( world - > progs , ed - > v - > classname ) ) ;
return false ;
}
2016-01-18 05:22:07 +00:00
ptr_elements = ( int * ) BZ_Malloc ( numindexes * sizeof ( * ptr_elements ) ) ;
ptr_verts = ( float * ) BZ_Malloc ( numverts * sizeof ( vec3_t ) ) ;
2015-02-02 08:01:53 +00:00
numverts = 0 ;
numindexes = 0 ;
for ( sno = 0 ; sno < mod - > nummodelsurfaces ; sno + + )
{
surf = & mod - > surfaces [ sno + mod - > firstmodelsurface ] ;
if ( surf - > flags & ( SURF_DRAWSKY | SURF_DRAWTURB ) )
continue ;
if ( surf - > mesh )
{
mesh = surf - > mesh ;
for ( i = 0 ; i < mesh - > numvertexes ; i + + )
2016-01-18 05:22:07 +00:00
VectorSubtract ( mesh - > xyz_array [ i ] , geomcenter , ( ptr_verts + 3 * ( numverts + i ) ) ) ;
2015-02-02 08:01:53 +00:00
for ( i = 0 ; i < mesh - > numindexes ; i + = 3 )
{
//flip the triangles as we go
2016-01-18 05:22:07 +00:00
ptr_elements [ numindexes + i + 0 ] = numverts + mesh - > indexes [ i + 2 ] ;
ptr_elements [ numindexes + i + 1 ] = numverts + mesh - > indexes [ i + 1 ] ;
ptr_elements [ numindexes + i + 2 ] = numverts + mesh - > indexes [ i + 0 ] ;
2015-02-02 08:01:53 +00:00
}
numverts + = mesh - > numvertexes ;
numindexes + = i ;
}
else
{
float * vec ;
medge_t * edge ;
int lindex ;
for ( i = 0 ; i < surf - > numedges ; i + + )
{
lindex = mod - > surfedges [ surf - > firstedge + i ] ;
if ( lindex > 0 )
{
edge = & mod - > edges [ lindex ] ;
vec = mod - > vertexes [ edge - > v [ 0 ] ] . position ;
}
else
{
edge = & mod - > edges [ - lindex ] ;
vec = mod - > vertexes [ edge - > v [ 1 ] ] . position ;
}
2016-01-18 05:22:07 +00:00
VectorSubtract ( vec , geomcenter , ( ptr_verts + 3 * ( numverts + i ) ) ) ;
2015-02-02 08:01:53 +00:00
}
for ( i = 2 ; i < surf - > numedges ; i + + )
{
//quake is backwards, not ode
2016-01-18 05:22:07 +00:00
ptr_elements [ numindexes + + ] = numverts + i ;
ptr_elements [ numindexes + + ] = numverts + i - 1 ;
ptr_elements [ numindexes + + ] = numverts ;
2015-02-02 08:01:53 +00:00
}
numverts + = surf - > numedges ;
}
}
2016-01-18 05:22:07 +00:00
ed - > ode . ode_element3i = ptr_elements ;
ed - > ode . ode_vertex3f = ptr_verts ;
2015-02-02 08:01:53 +00:00
ed - > ode . ode_numvertices = numverts ;
ed - > ode . ode_numtriangles = numindexes / 3 ;
return true ;
}
# include "com_mesh.h"
static qboolean GenerateCollisionMesh_Alias ( world_t * world , model_t * mod , wedict_t * ed , vec3_t geomcenter )
{
mesh_t mesh ;
unsigned int numverts ;
unsigned int numindexes , i ;
galiasinfo_t * inf ;
unsigned int surfnum = 0 ;
entity_t re ;
2016-01-18 05:22:07 +00:00
int * ptr_elements ;
float * ptr_verts ;
2015-02-02 08:01:53 +00:00
numverts = 0 ;
numindexes = 0 ;
//fill in the parts of the entity_t that Alias_GAliasBuildMesh needs.
world - > Get_FrameState ( world , ed , & re . framestate ) ;
re . fatness = ed - > xv - > fatness ;
re . model = mod ;
inf = ( galiasinfo_t * ) Mod_Extradata ( mod ) ;
while ( inf )
{
numverts + = inf - > numverts ;
numindexes + = inf - > numindexes ;
inf = inf - > nextsurf ;
}
if ( ! numindexes )
{
Con_DPrintf ( " entity %i (classname %s) has no geometry \n " , NUM_FOR_EDICT ( world - > progs , ( edict_t * ) ed ) , PR_GetString ( world - > progs , ed - > v - > classname ) ) ;
return false ;
}
2016-01-18 05:22:07 +00:00
ptr_elements = ( int * ) BZ_Malloc ( numindexes * sizeof ( * ptr_elements ) ) ;
ptr_verts = ( float * ) BZ_Malloc ( numverts * sizeof ( vec3_t ) ) ;
2015-02-02 08:01:53 +00:00
numverts = 0 ;
numindexes = 0 ;
inf = ( galiasinfo_t * ) Mod_Extradata ( mod ) ;
while ( inf )
{
Alias_GAliasBuildMesh ( & mesh , NULL , inf , surfnum + + , & re , false ) ;
for ( i = 0 ; i < mesh . numvertexes ; i + + )
2016-01-18 05:22:07 +00:00
VectorSubtract ( mesh . xyz_array [ i ] , geomcenter , ( ptr_verts + 3 * ( numverts + i ) ) ) ;
2015-02-02 08:01:53 +00:00
for ( i = 0 ; i < mesh . numindexes ; i + = 3 )
{
//flip the triangles as we go
2016-01-18 05:22:07 +00:00
ptr_elements [ numindexes + i + 0 ] = numverts + mesh . indexes [ i + 2 ] ;
ptr_elements [ numindexes + i + 1 ] = numverts + mesh . indexes [ i + 1 ] ;
ptr_elements [ numindexes + i + 2 ] = numverts + mesh . indexes [ i + 0 ] ;
2015-02-02 08:01:53 +00:00
}
numverts + = inf - > numverts ;
numindexes + = inf - > numindexes ;
inf = inf - > nextsurf ;
}
Alias_FlushCache ( ) ; //it got built using an entity on the stack, make sure other stuff doesn't get hurt.
2016-01-18 05:22:07 +00:00
ed - > ode . ode_element3i = ptr_elements ;
ed - > ode . ode_vertex3f = ptr_verts ;
2015-02-02 08:01:53 +00:00
ed - > ode . ode_numvertices = numverts ;
ed - > ode . ode_numtriangles = numindexes / 3 ;
return true ;
}
//Bullet has a fit if we have any degenerate triangles, so make sure we can determine some surface normal
2016-01-18 05:22:07 +00:00
static void CollisionMesh_CleanupMesh ( wedict_t * ed )
2015-02-02 08:01:53 +00:00
{
float * v1 , * v2 , * v3 ;
vec3_t d1 , d2 , cr ;
int in , out ;
for ( in = 0 , out = 0 ; in < ed - > ode . ode_numtriangles * 3 ; in + = 3 )
{
v1 = & ed - > ode . ode_vertex3f [ ed - > ode . ode_element3i [ in + 0 ] * 3 ] ;
v2 = & ed - > ode . ode_vertex3f [ ed - > ode . ode_element3i [ in + 1 ] * 3 ] ;
v3 = & ed - > ode . ode_vertex3f [ ed - > ode . ode_element3i [ in + 2 ] * 3 ] ;
VectorSubtract ( v3 , v1 , d1 ) ;
VectorSubtract ( v2 , v1 , d2 ) ;
CrossProduct ( d1 , d2 , cr ) ;
if ( DotProduct ( cr , cr ) = = 0 )
continue ;
ed - > ode . ode_element3i [ out + 0 ] = ed - > ode . ode_element3i [ in + 0 ] ;
ed - > ode . ode_element3i [ out + 1 ] = ed - > ode . ode_element3i [ in + 1 ] ;
ed - > ode . ode_element3i [ out + 2 ] = ed - > ode . ode_element3i [ in + 2 ] ;
out + = 3 ;
}
ed - > ode . ode_numtriangles = out / 3 ;
}
qboolean QDECL World_GenerateCollisionMesh ( world_t * world , model_t * mod , wedict_t * ed , vec3_t geomcenter )
{
qboolean result ;
switch ( mod - > type )
{
case mod_brush :
result = GenerateCollisionMesh_BSP ( world , mod , ed , geomcenter ) ;
break ;
case mod_alias :
result = GenerateCollisionMesh_Alias ( world , mod , ed , geomcenter ) ;
break ;
case mod_heightmap :
case mod_halflife :
case mod_sprite :
case mod_dummy :
default :
return false ; //panic!
}
if ( result )
{
2016-01-18 05:22:07 +00:00
CollisionMesh_CleanupMesh ( ed ) ;
2015-02-02 08:01:53 +00:00
if ( ed - > ode . ode_numtriangles > 0 )
return true ;
}
return false ;
}
void QDECL World_ReleaseCollisionMesh ( wedict_t * ed )
{
BZ_Free ( ed - > ode . ode_element3i ) ;
ed - > ode . ode_element3i = NULL ;
BZ_Free ( ed - > ode . ode_vertex3f ) ;
ed - > ode . ode_vertex3f = NULL ;
ed - > ode . ode_numvertices = 0 ;
ed - > ode . ode_numtriangles = 0 ;
}
# endif
2004-11-29 01:21:00 +00:00
# endif