Esempio n. 1
0
// [30/7/2012] Added Monster_CheckBottom ~hogsy
bool Monster_CheckBottom(edict_t *ent)
{
	vec3_t	mins,maxs,start,stop;
	trace_t	trace;
	int		x,y;
	float	mid,bottom;

	Math_VectorAdd(ent->v.origin,ent->v.mins,mins);
	Math_VectorAdd(ent->v.origin,ent->v.maxs,maxs);

	/*	If all of the points under the corners are solid world, don't bother
		with the tougher checks
		the corners must be within 16 of the midpoint
	*/
	start[2] = mins[2]-1;
	for(x = 0; x <= 1; x++)
		for(y = 0; y <= 1; y++)
		{
			start[0] = x ? maxs[0] : mins[0];
			start[1] = y ? maxs[1] : mins[1];
			if(Engine.Server_PointContents(start) != BSP_CONTENTS_SOLID)
			{
				start[2] = mins[2];

				// The midpoint must be within 16 of the bottom
				start[0]	= stop[0]	= (mins[0]+maxs[0])*0.5f;
				start[1]	= stop[1]	= (mins[1]+maxs[1])*0.5f;

				stop[2]	= start[2]-2*MONSTER_STEPSIZE;

				trace = Engine.Server_Move(start,mv3Origin,mv3Origin,stop,true,ent);
				if(trace.fraction == 1.0)
					return false;

				mid = bottom = trace.endpos[2];

				// The corners must be within 16 of the midpoint
				for(x = 0; x <= 1; x++)
					for(y = 0; y <= 1; y++)
					{
						start[0] = stop[0] = x ? maxs[0] : mins[0];
						start[1] = stop[1] = x ? maxs[1] : mins[1];

						trace = Engine.Server_Move(start,mv3Origin,mv3Origin,stop,true,ent);
						if(trace.fraction != 1.0 && trace.endpos[2] > bottom)
							bottom = trace.endpos[2];
						if(trace.fraction == 1.0 || mid-trace.endpos[2] > MONSTER_STEPSIZE)
							return false;
					}
			}
		}

	return true;
}
void Sky_DrawFace (int axis)
{
	glpoly_t	*p;
	MathVector3f_t verts[4];
	int			i, j, start;
	float		di,qi,dj,qj;
	MathVector3f_t v_up, v_right, temp, temp2;

	Sky_SetBoxVert(-1.0f,-1.0f,axis,verts[0]);
	Sky_SetBoxVert(-1.0f,1.0f,axis,verts[1]);
	Sky_SetBoxVert(1.0f,1.0f,axis,verts[2]);
	Sky_SetBoxVert(1.0f,-1.0f,axis,verts[3]);

	start = Hunk_LowMark ();
	p = (glpoly_t*)Hunk_Alloc(sizeof(glpoly_t));

	Math_VectorSubtract(verts[2],verts[3], v_up);
	Math_VectorSubtract(verts[2],verts[1], v_right);

	di = Math_Max((int)r_sky_quality.value,1);
	qi = 1.0f/di;
	dj = (axis < 4) ? di*2 : di; // Subdivide vertically more than horizontally on skybox sides
	qj = 1.0f/dj;

	for (i=0; i<di; i++)
	{
		for (j=0; j<dj; j++)
		{
			if (i*qi < skymins[0][axis]/2+0.5 - qi || i*qi > skymaxs[0][axis]/2+0.5 ||
				j*qj < skymins[1][axis]/2+0.5 - qj || j*qj > skymaxs[1][axis]/2+0.5)
				continue;

			//if (i&1 ^ j&1) continue; //checkerboard test
			Math_VectorScale(v_right, qi*i, temp);
			Math_VectorScale(v_up, qj*j, temp2);
			Math_VectorAdd(temp,temp2,temp);
			Math_VectorAdd(verts[0],temp,p->verts[0]);

			Math_VectorScale(v_up, qj, temp);
			Math_VectorAdd(p->verts[0],temp,p->verts[1]);

			Math_VectorScale(v_right, qi, temp);
			Math_VectorAdd(p->verts[1],temp,p->verts[2]);

			Math_VectorAdd(p->verts[0],temp,p->verts[3]);

			Sky_DrawFaceQuad(p);
		}
	}

	Hunk_FreeToLowMark(start);
}
Esempio n. 3
0
bool Monster_IsVisible(edict_t *ent,edict_t *target)
{
	trace_t	tTrace;
	vec3_t	vStart,vEnd;

	// [10/4/2013] TODO: Rework for new FOV system ~hogsy
	// [2/1/2013] Simplified ~hogsy
	Math_VectorAdd(ent->v.origin,ent->v.view_ofs,vStart);
	Math_VectorAdd(target->v.origin,target->v.view_ofs,vEnd);

	tTrace = Traceline(ent,vStart,vEnd,true);
	// [10/4/2013] Simplified ~hogsy
	if(!(tTrace.bOpen && tTrace.bWater) && tTrace.fraction == 1.0f)
		return true;

	return false;
}
Esempio n. 4
0
void Brush_Move (brush_t *b, vec3_t move)
{
	int		i;
	face_t	*f;

	for (f=b->brush_faces ; f ; f=f->next)
		for (i=0 ; i<3 ; i++)
			Math_VectorAdd(f->planepts[i],move,f->planepts[i]);

	Brush_Build(b);
}
/*	draw bounding boxes -- the server-side boxes, not the renderer cullboxes
*/
void Video_ShowBoundingBoxes(void)
{
	extern ServerEntity_t	*sv_player;
	MathVector3f_t			mins, maxs;
	ClientEntity_t			*clEntity;
	ServerEntity_t			*ed;
	int						i;

	if (!r_showbboxes.value || (cl.maxclients > 1) || !r_drawentities.value || (!sv.active && !g_state.embedded))
		return;

	VideoLayer_Disable(VIDEO_DEPTH_TEST | VIDEO_TEXTURE_2D);
	VideoLayer_Enable(VIDEO_BLEND);

	for (i=0, ed=NEXT_EDICT(sv.edicts) ; i<sv.num_edicts ; i++, ed=NEXT_EDICT(ed))
	{
		if(ed == sv_player && !chase_active.value)
			continue;

		glColor3f(1,1,1);

		R_EmitWirePoint (ed->v.origin);

		Math_VectorAdd(ed->v.mins,ed->v.origin,mins);
		Math_VectorAdd(ed->v.maxs,ed->v.origin,maxs);

		glColor4f(0, 0.5f, 0, 0.5f);

		R_EmitWireBox(mins,maxs, 1, 1, 1);
	}

	// Cycle through client-side entities.
	for (i = 0, clEntity = cl_entities; i < cl.num_entities; i++, clEntity++)
		Video_DrawClientBoundingBox(clEntity);
	for (i = 0, clEntity = cl_temp_entities; i < cl_numvisedicts; i++, clEntity++)
		Video_DrawClientBoundingBox(clEntity);

	VideoLayer_Disable(VIDEO_BLEND);
	VideoLayer_Enable(VIDEO_TEXTURE_2D | VIDEO_DEPTH_TEST);
}
bool R_CullModelForEntity(entity_t *e)
{
	vec3_t mins, maxs;

	if(e == &cl.viewent)
		return false;

	if(e->angles[PITCH] || e->angles[ROLL])
	{
		Math_VectorAdd (e->origin, e->model->rmins, mins);
		Math_VectorAdd (e->origin, e->model->rmaxs, maxs);
	}
	else if(e->angles[YAW])
	{
		Math_VectorAdd (e->origin, e->model->ymins, mins);
		Math_VectorAdd (e->origin, e->model->ymaxs, maxs);
	}
	else //no rotation
	{
		Math_VectorAdd(e->origin,e->model->mins,mins);
		Math_VectorAdd(e->origin,e->model->maxs,maxs);
	}

	return R_CullBox(mins, maxs);
}
void Video_DrawClientBoundingBox(ClientEntity_t *clEntity)
{
	MathVector3f_t vMins, vMaxs;

	if (!clEntity->model || ((clEntity == &cl_entities[cl.viewentity]) && !chase_active.bValue) || (clEntity == &cl.viewent))
		return;

	Math_VectorAdd(clEntity->model->rmins, clEntity->origin, vMins);
	Math_VectorAdd(clEntity->model->rmaxs, clEntity->origin, vMaxs);

	switch (clEntity->model->type)
	{
	case MODEL_TYPE_LEVEL:
		// Only draw wires for the BSP, since otherwise it's difficult to see anything else.
		glColor4f(0, 0, 0, 0);
		R_EmitWireBox(vMins, vMaxs, 0, 1, 0);
		break;
	default:
		glColor4f(0.5f, 0, 0, 0.5f);
		R_EmitWireBox(vMins, vMaxs, 1, 0, 0);
	}
}
Esempio n. 8
0
/*	Damage entities within a specific radius.
*/
void Entity_RadiusDamage(edict_t *eInflictor,float fRadius,int iDamage,int iDamageType)
{
	int		i;
	float	fDistance;
	vec3_t	vOrigin;
	edict_t *eTarget = Engine.Server_FindRadius(eInflictor->v.origin,fRadius);

	Engine.WriteByte(MSG_BROADCAST,SVC_TEMPENTITY);
	Engine.WriteByte(MSG_BROADCAST,CTE_EXPLOSION);

	for(i = 0; i < 3; i++)
		Engine.WriteCoord(MSG_BROADCAST,eInflictor->v.origin[i]);

	do
	{
		if(eTarget->v.bTakeDamage)
		{
			int i;

			for(i = 0; i < 3; i++)
				vOrigin[i] = eTarget->v.origin[i]+(eTarget->v.mins[i]+eTarget->v.maxs[i])*0.5f;

			Math_VectorSubtract(eInflictor->v.origin,vOrigin,vOrigin);

			fDistance = 0.5f*(float)Math_VectorLength(vOrigin);
			if(fDistance > 0)
			{
				Math_VectorInverse(vOrigin);
				Math_VectorAdd(eTarget->v.velocity,vOrigin,eTarget->v.velocity);

				// [15/7/2013] Reduce the damage by distance ~hogsy
				fDistance = (float)iDamage-(100.0f/fDistance);

				// [15/8/2013] Less damage for the inflictor ~hogsy
				if(eTarget == eInflictor)
					fDistance = fDistance/2.0f;

				if(fDistance > 0)
					if(Entity_CanDamage(eInflictor,eTarget, iDamageType))
						MONSTER_Damage(eTarget,eInflictor,(int)fDistance,iDamageType);
			}
		}

		eTarget = eTarget->v.chain;
	}
	while(eTarget);
}
Esempio n. 9
0
/*	Damage entities within a specific radius.
*/
void Entity_RadiusDamage(ServerEntity_t *eInflictor, float fRadius, int iDamage, int iDamageType)
{
	int		i;
	float	fDistance;
	MathVector3f_t	vOrigin;
	ServerEntity_t *eTarget = Engine.Server_FindRadius(eInflictor->v.origin, fRadius);

	do
	{
		if(eTarget->v.bTakeDamage)
		{
			for(i = 0; i < 3; i++)
				vOrigin[i] = eTarget->v.origin[i]+(eTarget->v.mins[i]+eTarget->v.maxs[i])*0.5f;

			Math_VectorSubtract(eInflictor->v.origin,vOrigin,vOrigin);

			fDistance = 0.5f*(float)Math_VectorLength(vOrigin);
			if(fDistance > 0)
			{
				Math_VectorInverse(vOrigin);
				Math_VectorAdd(eTarget->v.velocity,vOrigin,eTarget->v.velocity);

				// Reduce the damage by distance.
				fDistance = (float)iDamage-(100.0f/fDistance);

				// Less damage for the inflictor.
				if(eTarget == eInflictor)
					fDistance = fDistance/2.0f;

				if(fDistance > 0)
					Entity_Damage(eTarget,eInflictor,(int)fDistance,iDamageType);
			}
		}

		eTarget = eTarget->v.chain;
	}
	while(eTarget);
}
Esempio n. 10
0
/*	Does not change the entities velocity at all
*/
trace_t SV_PushEntity (edict_t *ent, vec3_t push)
{
	trace_t	trace;
	vec3_t	end;

	Math_VectorAdd (ent->v.origin, push, end);

	if (ent->v.movetype == (MOVETYPE_FLYMISSILE || MOVETYPE_FLYBOUNCE))
		trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent);
	else if (ent->Physics.iSolid == SOLID_TRIGGER || ent->Physics.iSolid == SOLID_NOT)
	// only clip against bmodels
		trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
	else
		trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);

	Math_VectorCopy (trace.endpos, ent->v.origin);
	SV_LinkEdict(ent,true);

	if(trace.ent)
		Physics_Impact(ent,trace.ent);

	return trace;
}
Esempio n. 11
0
/*	Does not change the entities velocity at all
*/
trace_t Physics_PushEntity(ServerEntity_t *eEntity, MathVector3f_t mvPush)
{
	trace_t	trace;
	MathVector3f_t	end;

	Math_VectorAdd(eEntity->v.origin, mvPush, end);

	if (eEntity->v.movetype == (MOVETYPE_FLYMISSILE || MOVETYPE_FLYBOUNCE))
		trace = Engine.Server_Move(eEntity->v.origin, eEntity->v.mins, eEntity->v.maxs, end, MOVE_MISSILE, eEntity);
	else if (eEntity->Physics.iSolid == SOLID_TRIGGER || eEntity->Physics.iSolid == SOLID_NOT)
		// only clip against bmodels
		trace = Engine.Server_Move(eEntity->v.origin, eEntity->v.mins, eEntity->v.maxs, end, MOVE_NOMONSTERS, eEntity);
	else
		trace = Engine.Server_Move(eEntity->v.origin, eEntity->v.mins, eEntity->v.maxs, end, MOVE_NORMAL, eEntity);

	Math_VectorCopy(trace.endpos, eEntity->v.origin);
	Entity_Link(eEntity, true);

	if (trace.ent)
		Physics_Impact(eEntity, trace.ent);

	return trace;
}
Esempio n. 12
0
winding_t *BasePolyForPlane (plane_t *p)
{
	int			i, x;
	vec_t		max, v;
	vec3_t		org, vright, vup;
	winding_t	*w;

	// find the major axis
	max = -BOGUS_RANGE;
	x = -1;
	for (i=0 ; i<3; i++)
	{
		v = fabs(p->normal[i]);
		if (v > max)
		{
			x = i;
			max = v;
		}
	}

	if (x==-1)
		Error("BasePolyForPlane: no axis found");

	Math_VectorCopy(vec3_origin,vup);
	switch (x)
	{
	case 0:
	case 1:
		vup[2] = 1;
		break;
	case 2:
		vup[0] = 1;
		break;
	}


	v = Math_DotProduct(vup,p->normal);
	Math_VectorMA(vup,-v,p->normal,vup);
	Math_VectorNormalize(vup);

	Math_VectorScale(p->normal,p->dist,org);

	Math_CrossProduct(vup,p->normal,vright);

	Math_VectorScale(vup,8192,vup);
	Math_VectorScale(vright,8192,vright);

// project a really big	axis aligned box onto the plane
	w = NewWinding (4);

	Math_VectorSubtract(org,vright,w->points[0]);
	Math_VectorAdd(w->points[0],vup,w->points[0]);

	Math_VectorAdd(org,vright,w->points[1]);
	Math_VectorAdd(w->points[1],vup,w->points[1]);

	Math_VectorAdd(org,vright,w->points[2]);
	Math_VectorSubtract(w->points[2],vup,w->points[2]);

	Math_VectorSubtract(org,vright,w->points[3]);
	Math_VectorSubtract(w->points[3],vup,w->points[3]);

	w->numpoints = 4;

	return w;
}
Esempio n. 13
0
// [18/5/2013] TODO: Merge with SV_PushMove ~hogsy
static void Server_PushRotate(edict_t *pusher,float movetime)
{
	int		i,e,num_moved,slaves_moved;
	edict_t	*check,*block,*moved_edict[MAX_EDICTS],*ground,*slave,*master;
	vec3_t	move,a,amove,entorig,pushorig,moved_from[MAX_EDICTS],org,org2,forward,right,up;
	bool	bMoveIt;

	for (i = 0; i < 3; i++)
		amove[i] = pusher->v.avelocity[i] * movetime;

	Math_VectorNegate(amove,a);
	Math_AngleVectors(a,forward,right,up);

	Math_VectorCopy(pusher->v.angles,pushorig);

	// move the pusher to it's final position
	Math_VectorAdd(pusher->v.angles,amove,pusher->v.angles);

	pusher->v.ltime += movetime;
	SV_LinkEdict (pusher, false);

	slaves_moved = 0;
	master = pusher;
	while(master->v.aiment)
	{
		slave = PROG_TO_EDICT(master->v.aiment);

		slaves_moved++;
		Math_VectorCopy (slave->v.angles, moved_from[MAX_EDICTS - slaves_moved]);
		moved_edict[MAX_EDICTS - slaves_moved] = slave;

		if (slave->v.movedir[PITCH])
			slave->v.angles[PITCH] = master->v.angles[PITCH];
		else
			slave->v.angles[PITCH] += slave->v.avelocity[PITCH] * movetime;

		if (slave->v.movedir[YAW])
			slave->v.angles[YAW] = master->v.angles[YAW];
		else
			slave->v.angles[YAW] += slave->v.avelocity[YAW] * movetime;

		if (slave->v.movedir[ROLL])
			slave->v.angles[ROLL] = master->v.angles[ROLL];
		else
			slave->v.angles[ROLL] += slave->v.avelocity[ROLL] * movetime;

		slave->v.ltime = master->v.ltime;
		SV_LinkEdict(slave,false);

		master = slave;
	}

	// see if any solid entities are inside the final position
	num_moved = 0;
	check = NEXT_EDICT(sv.edicts);
	for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT(check))
	{
		if (check->free)
			continue;
		if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP)
			continue;

		// if the entity is standing on the pusher, it will definitely be moved
		bMoveIt = false;
		ground = check->v.groundentity;
		if(check->v.flags & FL_ONGROUND)
		{
			if (ground == pusher)
				bMoveIt = true;
			else
			{
				for (i = 0; i < slaves_moved; i++)
				{
					if (ground == moved_edict[MAX_EDICTS - i - 1])
					{
						bMoveIt = true;
						break;
					}
				}
			}
		}

		if(!bMoveIt)
		{
			if(	check->v.absmin[0] >= pusher->v.absmax[0]
			||	check->v.absmin[1] >= pusher->v.absmax[1]
			||	check->v.absmin[2] >= pusher->v.absmax[2]
			||	check->v.absmax[0] <= pusher->v.absmin[0]
			||	check->v.absmax[1] <= pusher->v.absmin[1]
			||	check->v.absmax[2] <= pusher->v.absmin[2])
			{
				for (i = 0; i < slaves_moved; i++)
				{
					slave = moved_edict[MAX_EDICTS-i-1];
					if( check->v.absmin[0] >= slave->v.absmax[0]
					||	check->v.absmin[1] >= slave->v.absmax[1]
					||	check->v.absmin[2] >= slave->v.absmax[2]
					||	check->v.absmax[0] <= slave->v.absmin[0]
					||	check->v.absmax[1] <= slave->v.absmin[1]
					||	check->v.absmax[2] <= slave->v.absmin[2] )
						continue;
				}
				if (i == slaves_moved)
					continue;
			}

			// See if the ent's bbox is inside the pusher's final position
			if(!SV_TestEntityPosition(check))
				continue;
		}

		// remove the onground flag for non-players
		if(check->v.movetype != MOVETYPE_WALK)
			check->v.flags = check->v.flags & ~FL_ONGROUND;

		Math_VectorCopy(check->v.origin,entorig);
		Math_VectorCopy(check->v.origin,moved_from[num_moved]);
		moved_edict[num_moved] = check;
		num_moved++;

		// calculate destination position
		Math_VectorSubtract(check->v.origin,pusher->v.origin,org);
		org2[0] = Math_DotProduct(org,forward);
		org2[1] = -Math_DotProduct(org,right);
		org2[2] = Math_DotProduct(org,up);
		Math_VectorSubtract (org2,org,move);

		// try moving the contacted entity
		pusher->Physics.iSolid = SOLID_NOT;
		SV_PushEntity (check, move);
	//@@TODO: do we ever want to do anybody's angles?  maybe just yaw???
		if(check->monster.iType != 1)
		{
#if 0
			vec3_t	vYaw;
			
			vYaw[YAW] = Math_AngleMod(pusher->v.angles[YAW]+check->v.angles[YAW]);

			Con_Printf("%i %i\n",(int)check->v.angles[YAW],(int)vYaw[YAW]);
			//check->v.angles[YAW] = vYaw[YAW];
			//check->v.angles[YAW] = Math_AngleMod(vYaw[YAW]);
#endif
			// move back any entities we already moved
			for (i = 0; i < num_moved; i++)
			{
				Math_VectorAdd(moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles);
				moved_edict[i]->v.angles[YAW] += amove[YAW]/2.0f;

				SV_LinkEdict(moved_edict[i],false);
			}
		}

		pusher->Physics.iSolid = SOLID_BSP;

		// If it is still inside the pusher, block
		block = SV_TestEntityPosition (check);
		if (block)
		{
			// fail the move
			if (check->v.mins[0] == check->v.maxs[0])
				continue;
			if (check->Physics.iSolid == SOLID_NOT || check->Physics.iSolid == SOLID_TRIGGER)
			{
				// corpse
				check->v.mins[0] = check->v.mins[1] = 0;
				Math_VectorCopy(check->v.mins,check->v.maxs);
				continue;
			}

			Math_VectorCopy(entorig,check->v.origin);
			SV_LinkEdict(check,true);

			Math_VectorCopy(pushorig,pusher->v.angles);
			SV_LinkEdict(pusher,false);
			pusher->v.ltime -= movetime;

			for(i = 0; i < slaves_moved; i++)
			{
				slave = moved_edict[MAX_EDICTS - i - 1];
				Math_VectorCopy(moved_from[MAX_EDICTS - i - 1], slave->v.angles);
				SV_LinkEdict(slave,false);
				slave->v.ltime -= movetime;
			}

			// if the pusher has a "blocked" function, call it
			// otherwise, just stay in place until the obstacle is gone
			if (pusher->v.blocked)
				pusher->v.blocked(pusher,check);

			// move back any entities we already moved
			for (i = 0; i < num_moved; i++)
			{
				Math_VectorCopy (moved_from[i], moved_edict[i]->v.origin);
			//@@TODO:: see above
			//	if (!((int)moved_edict[i]->v.flags & (FL_CLIENT | FL_MONSTER)))
				Math_VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles);
				moved_edict[i]->v.angles[YAW] -= amove[YAW];

				SV_LinkEdict(moved_edict[i],false);
			}
			return;
		}
	}
}
Esempio n. 14
0
void SV_PushMove (edict_t *pusher, float movetime)
{
	int			i, e;
	edict_t		*check, *block;
	vec3_t		mins, maxs, move;
	vec3_t		entorig, pushorig;
	int			num_moved;
	edict_t		**moved_edict; //johnfitz -- dynamically allocate
	vec3_t		*moved_from; //johnfitz -- dynamically allocate
	int			mark; //johnfitz

	if(!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
	{
		pusher->v.ltime += movetime;
		return;
	}

	for (i=0 ; i<3 ; i++)
	{
		move[i] = pusher->v.velocity[i] * movetime;
		mins[i] = pusher->v.absmin[i] + move[i];
		maxs[i] = pusher->v.absmax[i] + move[i];
	}

	Math_VectorCopy (pusher->v.origin, pushorig);

// move the pusher to it's final position

	Math_VectorAdd (pusher->v.origin, move, pusher->v.origin);
	pusher->v.ltime += movetime;
	SV_LinkEdict(pusher,false);

	//johnfitz -- dynamically allocate
	mark = Hunk_LowMark ();
	moved_edict = (edict_t**)Hunk_Alloc(sv.num_edicts*sizeof(edict_t*));
	moved_from	= (vec3_t(*))Hunk_Alloc (sv.num_edicts*sizeof(vec3_t));
	//johnfitz

// see if any solid entities are inside the final position
	num_moved = 0;
	check = NEXT_EDICT(sv.edicts);
	for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
	{
		if (check->free)
			continue;
		if (check->v.movetype == MOVETYPE_PUSH
		|| check->v.movetype == MOVETYPE_NONE
		|| check->v.movetype == MOVETYPE_NOCLIP)
			continue;

	// if the entity is standing on the pusher, it will definately be moved
		if(!((check->v.flags & FL_ONGROUND)	&& check->v.groundentity == pusher))
		{
			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;

		// see if the ent's bbox is inside the pusher's final position
			if (!SV_TestEntityPosition (check))
				continue;
		}

	// remove the onground flag for non-players
		if (check->v.movetype != MOVETYPE_WALK)
			check->v.flags = check->v.flags & ~FL_ONGROUND;

		Math_VectorCopy(check->v.origin,entorig);
		Math_VectorCopy(check->v.origin,moved_from[num_moved]);
		moved_edict[num_moved] = check;
		num_moved++;

		// try moving the contacted entity
		pusher->Physics.iSolid = SOLID_NOT;
		SV_PushEntity (check, move);
		pusher->Physics.iSolid = SOLID_BSP;

	// if it is still inside the pusher, block
		block = SV_TestEntityPosition (check);
		if (block)
		{	// fail the move
			if (check->v.mins[0] == check->v.maxs[0])
				continue;
			if (check->Physics.iSolid == SOLID_NOT || check->Physics.iSolid == SOLID_TRIGGER)
			{	// corpse
				check->v.mins[0] = check->v.mins[1] = 0;
				Math_VectorCopy(check->v.mins,check->v.maxs);
				continue;
			}

			Math_VectorCopy(entorig,check->v.origin);
			SV_LinkEdict(check,true);

			Math_VectorCopy(pushorig,pusher->v.origin);
			SV_LinkEdict(pusher,false);
			pusher->v.ltime -= movetime;

			// if the pusher has a "blocked" function, call it
			// otherwise, just stay in place until the obstacle is gone
			if(pusher->v.blocked)
			{
				pr_global_struct.self	= EDICT_TO_PROG(pusher);
				pr_global_struct.eOther	= check;

				pusher->v.blocked(pusher,check);
			}

		// move back any entities we already moved
			for (i=0 ; i<num_moved ; i++)
			{
				Math_VectorCopy(moved_from[i],moved_edict[i]->v.origin);
				SV_LinkEdict (moved_edict[i], false);
			}
			Hunk_FreeToLowMark (mark); //johnfitz
			return;
		}
	}

	Hunk_FreeToLowMark (mark); //johnfitz
}
Esempio n. 15
0
// [30/7/2012] Added Monster_MoveStep ~hogsy
// [30/7/2012] TODO: Revised ~hogsy
bool Monster_MoveStep(edict_t *ent,vec3_t move,bool bRelink)
{
	float	dz;
	vec3_t	oldorg,vNewOrigin,end;
	trace_t	trace;
	int		i;

	Math_VectorClear(vNewOrigin);

	// Flying monsters don't step up
	if(ent->v.flags & (FL_SWIM|FL_FLY))
	{
		// Try one move with vertical motion, then one without
		for(i = 0; i < 2; i++)
		{
			Math_VectorAdd(ent->v.origin,move,vNewOrigin);

			if(i == 0)
			{
				dz = ent->v.origin[2]-ent->monster.vTarget[2];
				if(dz > 40)
					vNewOrigin[2] -= 8;
				else if(dz < 30)
					vNewOrigin[2] += 8;
			}

			trace = Engine.Server_Move(ent->v.origin,ent->v.mins,ent->v.maxs,vNewOrigin,false,ent);
			if(trace.fraction == 1.0f)
			{
				if((ent->v.flags & FL_SWIM) && (Engine.Server_PointContents(trace.endpos) == BSP_CONTENTS_EMPTY))
					return false;

				Math_VectorCopy(trace.endpos,ent->v.origin);

				if(bRelink)
					Engine.LinkEntity(ent,true);

				return true;
			}
		}

		return false;
	}

	// Push down from a step height above the wished position
	vNewOrigin[2] += MONSTER_STEPSIZE;

	Math_VectorCopy(vNewOrigin,end);

	end[2] -= MONSTER_STEPSIZE*2;

	trace = Engine.Server_Move(vNewOrigin,ent->v.mins,ent->v.maxs,end,false,ent);
	if(trace.bAllSolid)
		return false;
	else if(trace.bStartSolid)
	{
		vNewOrigin[2] -= MONSTER_STEPSIZE;

		trace = Engine.Server_Move(vNewOrigin,ent->v.mins,ent->v.maxs,end,false,ent);
		if(trace.bAllSolid || trace.bStartSolid)
			return false;
	}

	if(trace.fraction == 1)
	{
		// If monster had the ground pulled out, go ahead and fall
		if(ent->v.flags & FL_PARTIALGROUND)
		{
			Math_VectorAdd(ent->v.origin,move,ent->v.origin);

			if(bRelink)
				Engine.LinkEntity(ent,true);

			ent->v.flags &= ~FL_ONGROUND;

			return true;
		}

		// Walked off an edge
		return false;
	}

	// Check point traces down for dangling corners
	Math_VectorCopy(trace.endpos,ent->v.origin);

	if(!Monster_CheckBottom(ent))
	{
		if(ent->v.flags & FL_PARTIALGROUND)
		{
			/*	Entity had floor mostly
				pulled out from underneath
				it and is trying to correct
			*/
			if(bRelink)
				Engine.LinkEntity(ent,true);

			return true;
		}

		Math_VectorCopy(ent->v.origin,oldorg);

		return false;
	}

	if(ent->v.flags & FL_PARTIALGROUND)
		ent->v.flags &= ~FL_PARTIALGROUND;

	ent->v.groundentity = trace.ent;

	if(bRelink)
		Engine.LinkEntity(ent,true);

	return true;
}
Esempio n. 16
0
void Sky_ProcessEntities(void)
{
	int				i,k,mark;
	unsigned int	j;
	float			dot;
	bool			bRotated;
	ClientEntity_t	*e;
	msurface_t		*s;
	glpoly_t		*p;
	MathVector3f_t	vTemp, forward, right, up;

	if (!r_drawentities.value)
		return;

	for (i=0 ; i<cl_numvisedicts ; i++)
	{
		e = cl_visedicts[i];

		if (e->model->type != MODEL_TYPE_LEVEL)
			continue;

		if(R_CullModelForEntity(e))
			continue;

		if(e->alpha == ENTALPHA_ZERO)
			continue;

		Math_VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
		if(e->angles[0] || e->angles[1] || e->angles[2])
		{
			bRotated = true;

			Math_AngleVectors(e->angles, forward, right, up);
			Math_VectorCopy(modelorg,vTemp);

			modelorg[0] = Math_DotProduct(vTemp,forward);
			modelorg[1] = -Math_DotProduct(vTemp,right);
			modelorg[2] = Math_DotProduct(vTemp,up);
		}
		else
			bRotated = false;

		s = &e->model->surfaces[e->model->firstmodelsurface];

		for (j=0 ; j<e->model->nummodelsurfaces ; j++, s++)
		{
			if (s->flags & SURF_DRAWSKY)
			{
				dot = Math_DotProduct (modelorg, s->plane->normal) - s->plane->dist;
				if (((s->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
					(!(s->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
				{
					//copy the polygon and translate manually, since Sky_ProcessPoly needs it to be in world space
					mark = Hunk_LowMark();
					p = (glpoly_t*)Hunk_Alloc (sizeof(*s->polys)); //FIXME: don't allocate for each poly
					p->numverts = s->polys->numverts;
					for (k=0; k<p->numverts; k++)
					{
						if(bRotated)
						{
							p->verts[k][0] = e->origin[0] + s->polys->verts[k][0] * forward[0]
														  - s->polys->verts[k][1] * right[0]
														  + s->polys->verts[k][2] * up[0];
							p->verts[k][1] = e->origin[1] + s->polys->verts[k][0] * forward[1]
														  - s->polys->verts[k][1] * right[1]
														  + s->polys->verts[k][2] * up[1];
							p->verts[k][2] = e->origin[2] + s->polys->verts[k][0] * forward[2]
														  - s->polys->verts[k][1] * right[2]
														  + s->polys->verts[k][2] * up[2];
						}
						else
							Math_VectorAdd(s->polys->verts[k], e->origin, p->verts[k]);
					}
					Sky_ProcessPoly (p);
					Hunk_FreeToLowMark (mark);
				}
			}
		}
	}
}
Esempio n. 17
0
/*	Update sky bounds
*/
void Sky_ProjectPoly (int nump, MathVector3f_t vecs)
{
	int				i,j;
	MathVector3f_t	v, av;
	float			s, t, dv;
	int				axis;
	float			*vp;

	// decide which face it maps to
	Math_VectorCopy (g_mvOrigin3f, v);
	for (i=0, vp=vecs ; i<nump ; i++, vp+=3)
		Math_VectorAdd (vp, v, v);

	av[0] = fabs(v[0]);
	av[1] = fabs(v[1]);
	av[2] = fabs(v[2]);
	if (av[0] > av[1] && av[0] > av[2])
	{
		if (v[0] < 0)
			axis = 1;
		else
			axis = 0;
	}
	else if (av[1] > av[2] && av[1] > av[0])
	{
		if (v[1] < 0)
			axis = 3;
		else
			axis = 2;
	}
	else
	{
		if (v[2] < 0)
			axis = 5;
		else
			axis = 4;
	}

	// project new texture coords
	for (i=0 ; i<nump ; i++, vecs+=3)
	{
		j = vec_to_st[axis][2];
		if (j > 0)
			dv = vecs[j - 1];
		else
			dv = -vecs[-j - 1];

		j = vec_to_st[axis][0];
		if (j < 0)
			s = -vecs[-j -1] / dv;
		else
			s = vecs[j-1] / dv;
		j = vec_to_st[axis][1];
		if (j < 0)
			t = -vecs[-j -1] / dv;
		else
			t = vecs[j-1] / dv;

		if (s < skymins[0][axis])
			skymins[0][axis] = s;
		if (t < skymins[1][axis])
			skymins[1][axis] = t;
		if (s > skymaxs[0][axis])
			skymaxs[0][axis] = s;
		if (t > skymaxs[1][axis])
			skymaxs[1][axis] = t;
	}
}