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);
}
void C4Vizatergo_Think(ServerEntity_t *ent)
{
#if 0	// TODO: Finish?
	float	fDistance;
	vec3_t	vDistance;
	ServerEntity_t *eDistantEnt = Game.Server_FindRadius(ent->v.origin,512.0f);

	if(eDistantEnt)
	{
		Math_VectorSubtract(eDistantEnt->v.origin,ent->v.origin,vDistance);
		fDistance = 512.0f-Math_Length(vDistance);

		Game.Con_Printf("Distance: %f\n",fDistance);
		if(fDistance > 0)
			Sound(ent,CHAN_AUTO,"weapons/c4/c4beep.wav",255,ATTN_NORM);
	}
	else
		fDistance = 0;

	ent->v.dNextThink = Server.dTime+(2.5f*(fDistance/100.0f));
#else
	Sound(ent, CHAN_AUTO, "weapons/c4/beep.wav", 130, ATTN_IDLE);

	if(!ent->local.eOwner && ent->local.hit)
		ent->v.movetype = MOVETYPE_BOUNCE;

	ent->v.dNextThink = Server.dTime+2.5;
#endif
}
Esempio n. 3
0
void Select_AplyMatrix (void)
{
	brush_t	*b;
	face_t	*f;
	int		i, j;
	vec3_t	temp;

	for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
	{
		for (f=b->brush_faces ; f ; f=f->next)
		{
			for (i=0 ; i<3 ; i++)
			{
				Math_VectorSubtract(f->planepts[i],select_origin, temp);
				for (j=0 ; j<3 ; j++)
					f->planepts[i][j] = Math_DotProduct(temp,select_matrix[j])
						+ select_origin[j];
			}

			if (select_fliporder)
			{
				Math_VectorCopy(f->planepts[0],temp);
				Math_VectorCopy(f->planepts[2],f->planepts[0]);
				Math_VectorCopy(temp,f->planepts[2]);
			}
		}
		Brush_Build( b );
	}
	Sys_UpdateWindows (W_ALL);
}
// TODO: stay at least 8 units away from all walls in this leaf
void Chase_UpdateForDrawing (void)
{
	int		i;
	vec3_t	forward, up, right;
	vec3_t	ideal, crosshair, temp;

	Math_AngleVectors(cl.viewangles, forward, right, up);

	// calc ideal camera location before checking for walls
	for (i=0 ; i<3 ; i++)
		ideal[i] = cl.viewent.origin[i]
		- forward[i]*chase_back.value
		+ right[i]*chase_right.value;
		//+ up[i]*chase_up.value;
	ideal[2] = cl.viewent.origin[2] + chase_up.value;

	// make sure camera is not in or behind a wall
	TraceLine(r_refdef.vieworg, ideal, temp);
	if(Math_Length(temp) != 0)
		Math_VectorCopy(temp, ideal);

	// place camera
	Math_VectorCopy(ideal, r_refdef.vieworg);

	// find the spot the player is looking at
	Math_VectorMA(cl.viewent.origin, 4096, forward, temp);
	TraceLine(cl.viewent.origin, temp, crosshair);

	// calculate camera angles to look at the same spot
	Math_VectorSubtract(crosshair,r_refdef.vieworg,temp);
	Math_VectorAngles (temp, r_refdef.viewangles);
	if (r_refdef.viewangles[PITCH] == 90 || r_refdef.viewangles[PITCH] == -90)
		r_refdef.viewangles[YAW] = cl.viewangles[YAW];
}
Esempio n. 5
0
/*	Returns the visible polygon on a face
*/
winding_t *MakeFaceWinding(brush_t *b,face_t *face)
{
	winding_t	*w;
	face_t		*clip;
	plane_t		plane;
	BOOL		past;

	// get a poly that covers an effectively infinite area
	w = BasePolyForPlane (&face->plane);

	// chop the poly by all of the other faces
	past = FALSE;
	for (clip = b->brush_faces ; clip && w ; clip=clip->next)
	{
		if (clip == face)
		{
			past = TRUE;
			continue;
		}
		if(Math_DotProduct (face->plane.normal, clip->plane.normal) > 0.999
			&& fabs(face->plane.dist - clip->plane.dist) < 0.01 )
		{	// identical plane, use the later one
			if (past)
			{
				free (w);
				return NULL;
			}
			continue;
		}

		// flip the plane, because we want to keep the back side
		Math_VectorSubtract(vec3_origin,clip->plane.normal,plane.normal);
		plane.dist = -clip->plane.dist;

		w = ClipWinding(w,&plane,FALSE);
		if (!w)
			return w;
	}

	if (w->numpoints < 3)
	{
		free(w);
		w = NULL;
	}

	if (!w)
		printf ("unused plane\n");

	return w;
}
Waypoint_t *Waypoint_GetByType(MathVector3f_t position, WaypointType_t type, float distance)
{
	Waypoint_t		*point;
	MathVector3f_t	vecdist;

	for (point = wWaypoints; point->number < waypoint_count; point++)
		if (point->wType == type)
		{
			Math_VectorSubtract(position, point->position, vecdist);
			if (Math_Length(vecdist) < distance)
				return point;
		}

	return NULL;
}
Esempio n. 7
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);
}
// [20/9/2012] Lets us find a specific waypoint by name ~hogsy
Waypoint_t *Waypoint_GetByName(ServerEntity_t *eMonster,char *cName,float fMaxDistance)
{
	Waypoint_t	*wPoint;
	vec3_t		vDistance;

	for (wPoint = wWaypoints; wPoint->number < waypoint_count; wPoint++)
		if(strcmp(wPoint->cName,cName))
		{
			// [20/9/2012] TODO: Needs testing :[ ~hogsy
			Math_VectorSubtract(eMonster->v.origin,wPoint->position,vDistance);
			if(Math_Length(vDistance) < fMaxDistance)
				return wPoint;
		}

	// [20/9/2012] Welp we didn't find anything, return null ~hogsy
	return NULL;
}
Esempio n. 9
0
/*	Returns the range from an entity to a target.
*/
float MONSTER_GetRange(edict_t *ent,vec3_t target)
{
	// [12/4/2012] Revised ~hogsy
	vec3_t spot,spot1,spot2;

	spot1[0] = ent->v.origin[0]+ent->v.view_ofs[0];
	spot1[1] = ent->v.origin[1]+ent->v.view_ofs[1];
	spot1[2] = ent->v.origin[2]+ent->v.view_ofs[2];
	spot2[0] = target[0]; //+ target->v.view_ofs[0];
	spot2[1] = target[1]; //+ target->v.view_ofs[1];
	spot2[2] = target[2]; //+ target->v.view_ofs[2];

	Math_VectorSubtract(spot1,spot2,spot);

	// [4/2/2013] Shouldn't this be a float rather than a double? Oh well, whatever you say, Carmack ~hogsy
	return (float)Math_VectorLength(spot);
}
Esempio n. 10
0
/*	Itersects a ray with a brush
	Returns the face hit and the distance along the ray the intersection occured at
	Returns NULL and 0 if not hit at all
*/
face_t *Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist)
{
	face_t	*f, *firstface=NULL;
	vec3_t	p1, p2;
	float	frac, d1, d2;
	int		i;

	Math_VectorCopy(origin,p1);
	for (i=0 ; i<3 ; i++)
		p2[i] = p1[i] + dir[i]*16384;

	for (f=b->brush_faces ; f ; f=f->next)
	{
		d1 = Math_DotProduct(p1,f->plane.normal)-f->plane.dist;
		d2 = Math_DotProduct(p2,f->plane.normal)-f->plane.dist;
		if (d1 >= 0 && d2 >= 0)
		{
			*dist = 0;
			return NULL;	// ray is on front side of face
		}
		if (d1 <=0 && d2 <= 0)
			continue;
	// clip the ray to the plane
		frac = d1 / (d1 - d2);
		if (d1 > 0)
		{
			firstface = f;
			for (i=0 ; i<3 ; i++)
				p1[i] = p1[i] + frac *(p2[i] - p1[i]);
		}
		else
		{
			for (i=0 ; i<3 ; i++)
				p2[i] = p1[i] + frac *(p2[i] - p1[i]);
		}
	}

	// find distance p1 is along dir
	Math_VectorSubtract(p1,origin,p1);
	d1 = Math_DotProduct(p1,dir);

	*dist = d1;

	return firstface;
}
Esempio n. 11
0
void Sky_ProcessPoly (glpoly_t	*p)
{
	int				i;
	MathVector3f_t	verts[MAX_CLIP_VERTS];

	// Draw it
	DrawGLPoly(p);

	rs_brushpasses++;

	// Update sky bounds
	if (!r_fastsky.value)
	{
		for (i=0 ; i<p->numverts ; i++)
			Math_VectorSubtract (p->verts[i], r_origin, verts[i]);
		Sky_ClipPoly (p->numverts, verts[0], 0);
	}
}
Esempio n. 12
0
void Sky_GetTexCoord(MathVector3f_t v,float speed,float *s,float *t)
{
	MathVector3f_t	vDirection;
	float			fLength,fScroll;

	Math_VectorSubtract(v,r_origin,vDirection);

	vDirection[2] *= 3.0f;	// Flatten the sphere

	fLength = vDirection[0]*vDirection[0]+vDirection[1]*vDirection[1]+vDirection[2]*vDirection[2];
	fLength = sqrt(fLength);
	fLength = 6.0f*63.0f/fLength;

	fScroll = cl.time*speed;
	fScroll -= (int)fScroll & ~127;

	*s = (fScroll+vDirection[0]*fLength)*(1.0f/128.0f);
	*t = (fScroll+vDirection[1]*fLength)*(1.0f/128.0f);
}
Esempio n. 13
0
/*	Alternative to SetSize.
*/
void Entity_SetSizeVector(edict_t *eEntity,vec3_t vMin,vec3_t vMax)
{
	int	i;

	// [13/9/2013] Check if the model is set yet, if not give us a little warning ~hogsy
	if(!eEntity->v.model)
		Engine.Con_Warning("Setting entity size before model! (%s)\n",eEntity->v.cClassname);

	for(i = 0; i < 3; i++)
		if(vMin[i] > vMax[i])
		{
			Engine.Con_Warning("Backwards mins/maxs! (%s)\n",eEntity->v.cClassname);
			return;
		}

	Math_VectorCopy(vMin,eEntity->v.mins);
	Math_VectorCopy(vMax,eEntity->v.maxs);
	Math_VectorSubtract(vMax,vMin,eEntity->v.size);

	Engine.LinkEntity(eEntity,false);
}
Esempio n. 14
0
void SV_WallFriction (edict_t *ent, trace_t *trace)
{
	vec3_t		forward, right, up;
	float		d, i;
	vec3_t		into, side;

	Math_AngleVectors(ent->v.v_angle, forward, right, up);
	d = Math_DotProduct (trace->plane.normal, forward);

	d += 0.5;
	if (d >= 0)
		return;

	// Cut the tangential velocity
	i = Math_DotProduct (trace->plane.normal, ent->v.velocity);
	Math_VectorScale (trace->plane.normal, i, into);
	Math_VectorSubtract (ent->v.velocity, into, side);

	ent->v.velocity[0] = side[0] * (1 + d);
	ent->v.velocity[1] = side[1] * (1 + d);
}
Esempio n. 15
0
/*	Sets the size of the given entity; requires that the model has been applied first.
	Alternative to SetSize.
*/
void Entity_SetSizeVector(ServerEntity_t *eEntity, MathVector3f_t vMin, MathVector3f_t vMax)
{
	int	i;

	// Check if the model is set yet, if not give us a little warning.
	if(!eEntity->v.model)
		Engine.Con_Warning("Setting entity size before model! (%s)\n",eEntity->v.cClassname);

	for(i = 0; i < 3; i++)
		if(vMin[i] > vMax[i])
		{
			Engine.Con_Warning("Backwards mins/maxs! (%s)\n",eEntity->v.cClassname);
			return;
		}

	Math_VectorCopy(vMin,eEntity->v.mins);
	Math_VectorCopy(vMax,eEntity->v.maxs);
	Math_VectorSubtract(vMax,vMin,eEntity->v.size);

	Entity_Link(eEntity, false);
}
Esempio n. 16
0
void Physics_WallFriction(ServerEntity_t *eEntity, trace_t *trLine)
{
	MathVector3f_t forward, right, up;
	float d, i;
	MathVector3f_t into, side;

	Math_AngleVectors(eEntity->v.v_angle, forward, right, up);
	d = Math_DotProduct(trLine->plane.normal, forward);

	d += 0.5;
	if (d >= 0)
		return;

	// Cut the tangential velocity.
	i = Math_DotProduct(trLine->plane.normal, eEntity->v.velocity);
	Math_VectorScale(trLine->plane.normal, i, into);
	Math_VectorSubtract(eEntity->v.velocity, into, side);

	eEntity->v.velocity[0] = side[0] * (1 + d);
	eEntity->v.velocity[1] = side[1] * (1 + d);
}
Esempio n. 17
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);
}
void Waypoint_Spawn(MathVector3f_t vOrigin,WaypointType_t type)
{
#ifdef	DEBUG_WAYPOINT
	char		*cModelName = WAYPOINT_MODEL_BASE;
#endif
	int			iPointContents;
	Waypoint_t	*wPoint;

	/*	TODO
		If we're between two other waypoints
		and they can be seen then slot ourselves
		in so that we act as the last waypoint
		instead.
	*/

	iPointContents = Engine.Server_PointContents(vOrigin);
	// [17/6/2012] Check that this area is safe ~hogsy
	if(iPointContents == BSP_CONTENTS_SOLID)
	{
		Engine.Con_Warning("Failed to place waypoint, position is within a solid!\n");
		return;
	}

	{
		Waypoint_t *wVisibleWaypoint = Waypoint_GetByVisibility(vOrigin);
		// [30/1/2013] Oops! Check we actually have a visible waypoint!! ~hogsy
		if(wVisibleWaypoint)
		{
			MathVector3f_t vDistance;

			Math_VectorSubtract(wVisibleWaypoint->position,vOrigin,vDistance);
			if(Math_VectorLength(vDistance) < MONSTER_RANGE_MEDIUM)
			{
				Engine.Con_Printf("Invalid waypoint position!\n");
				return;
			}
		}
	}

	wPoint = Waypoint_Allocate();
	if(!wPoint)
	{
		Engine.Con_Warning("Failed to allocate waypoint!\n");
		return;
	}

	Math_VectorCopy(vOrigin,wPoint->position);

	wPoint->number	= waypoint_count;
	wPoint->bOpen	= false;
	wPoint->next	= Waypoint_GetByNumber(wPoint->number+1);
	wPoint->last	= Waypoint_GetByNumber(wPoint->number-1);
	wPoint->wType	= type;

	switch(type)
	{
	case WAYPOINT_ITEM:
		wPoint->cName = "item";
#ifdef DEBUG_WAYPOINT
		cModelName	= WAYPOINT_MODEL_ITEM;
#endif
		break;
	case WAYPOINT_CLIMB:
		wPoint->cName = "climb";
		// TODO: Check that there's a ladder nearby.
#ifdef DEBUG_WAYPOINT
		cModelName	= WAYPOINT_MODEL_CLIMB;
#endif
		break;
	case WAYPOINT_COVER:
		wPoint->cName = "cover";
		// [27/12/2012] TODO: Check that this is actually cover ~hogsy
		break;
	case WAYPOINT_TYPE_JUMP:
		wPoint->cName = "jump";
		// [27/12/2012] TODO: Check if this is actually a jump by tracing out ahead ~hogsy
#ifdef DEBUG_WAYPOINT
		cModelName	= WAYPOINT_MODEL_JUMP;
#endif
		break;
	case WAYPOINT_TYPE_SWIM:
		if(iPointContents != BSP_CONTENTS_WATER)
		{
			Engine.Con_Warning("Waypoint with type swim not within water contents (%i %i %i)!",
				(int)vOrigin[0],
				(int)vOrigin[1],
				(int)vOrigin[2]);

			Waypoint_Delete(wPoint);
			return;
		}

		wPoint->cName = "swim";
#ifdef DEBUG_WAYPOINT
		cModelName	= WAYPOINT_MODEL_SWIM;
#endif
		break;
	case WAYPOINT_TYPE_DEFAULT:
		wPoint->cName = "default";
		break;
	case WAYPOINT_SPAWN:
		wPoint->cName = "spawn";
		break;
	default:
		Engine.Con_Warning("Unknown waypoint type (%i)!\n",type);

		Waypoint_Delete(wPoint);
		return;
	}

	// [30/1/2013] Pathetic reordering... Ugh ~hogsy
	if(!wPoint->last)
	{
		wPoint->last = Waypoint_GetByVisibility(vOrigin);
		if(!wPoint->last)
		{
			Engine.Con_Warning("Failed to get another visible waypoint! (%i)\n",wPoint->number);
			return;
		}
	}
	else if(wPoint->last != wPoint && wPoint->last->next)
		wPoint->last->next = wPoint;

#ifdef DEBUG_WAYPOINT
	wPoint->eDebug = Entity_Spawn();
	if(wPoint->eDebug)
	{
		wPoint->eDebug->v.effects = EF_MOTION_ROTATE;

		Entity_SetModel(wPoint->eDebug,cModelName);
		Entity_SetSizeVector(wPoint->eDebug,g_mvOrigin3f,g_mvOrigin3f);
		Entity_SetOrigin(wPoint->eDebug,wPoint->position);
	}

	Engine.Con_DPrintf("Waypoint placed (%i %i %i)\n",
		(int)wPoint->position[0],
		(int)wPoint->position[1],
		(int)wPoint->position[2]);
	Engine.Con_DPrintf(" number: %i\n",wPoint->number);
	Engine.Con_DPrintf(" type:   %i\n",wPoint->wType);
#endif
}
Esempio n. 19
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. 20
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. 21
0
void Select_RotateAxis (int axis, float deg)
{
	vec3_t	temp;
	int		i, j;
	vec_t	c, s;

	if (deg == 0)
		return;

	Select_GetMid (select_origin);
	select_fliporder = FALSE;

	if (deg == 90)
	{
		for (i=0 ; i<3 ; i++)
		{
			Math_VectorCopy (vec3_origin, select_matrix[i]);
			select_matrix[i][i] = 1;
		}
		i = (axis+1)%3;
		j = (axis+2)%3;

		Math_VectorCopy(select_matrix[i],temp);
		Math_VectorCopy(select_matrix[j],select_matrix[i]);
		Math_VectorSubtract(vec3_origin,temp,select_matrix[j]);
	}
	else
	{
		deg = -deg;
		if (deg == -180)
		{
			c = -1;
			s = 0;
		}
		else if (deg == -270)
		{
			c = 0;
			s = -1;
		}
		else
		{
			c = cos(deg/180*3.14159);
			s = sin (deg/180*3.14159);
		}

		for (i=0 ; i<3 ; i++)
		{
			Math_VectorCopy (vec3_origin, select_matrix[i]);
			select_matrix[i][i] = 1;
		}

		switch (axis)
		{
		case 0:
			select_matrix[1][1] = c;
			select_matrix[1][2] = -s;
			select_matrix[2][1] = s;
			select_matrix[2][2] = c;
			break;
		case 1:
			select_matrix[0][0] = c;
			select_matrix[0][2] = s;
			select_matrix[2][0] = -s;
			select_matrix[2][2] = c;
			break;
		case 2:
			select_matrix[0][0] = c;
			select_matrix[0][1] = -s;
			select_matrix[1][0] = s;
			select_matrix[1][1] = c;
			break;
		}
	}

	Select_AplyMatrix ();
}
Esempio n. 22
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. 23
0
void Bot_Think(edict_t *eBot)
{
	// If the bot isn't dead, then add animations.
	if(eBot->monster.iState != STATE_DEAD)
	{
		if(eBot->v.flags & FL_ONGROUND)
		{
			if((	(eBot->v.velocity[0] < -4.0f || eBot->v.velocity[0] > 4.0f)	|| 
					(eBot->v.velocity[1] < -4.0f || eBot->v.velocity[1] > 4.0f))	&& 
					(!eBot->local.dAnimationTime || eBot->local.iAnimationEnd == 9))
				Entity_Animate(eBot,PlayerAnimation_Walk);
			else if((eBot->v.velocity[0] == 0 || eBot->v.velocity[1] == 0) && (!eBot->local.dAnimationTime || eBot->local.iAnimationEnd > 9))
			{
	#ifdef GAME_OPENKATANA
				if(eBot->v.iActiveWeapon == WEAPON_DAIKATANA)
					Entity_Animate(eBot,PlayerAnimation_KatanaIdle);
				else
	#endif
					Entity_Animate(eBot,PlayerAnimation_Idle);
			}
		}
	}

	switch(eBot->monster.iThink)
	{
	case THINK_IDLE:
#if 1
		// Add some random movement. ~hogsy
		if(rand()%120 == 0)
		{
			int	iResult = rand()%3;

			if(iResult == 0)
				eBot->v.velocity[0] += BOT_MIN_SPEED;
			else if(iResult == 1)
				eBot->v.velocity[0] -= BOT_MIN_SPEED;

			iResult = rand()%3;
			if(iResult == 0)
				eBot->v.velocity[1] += BOT_MIN_SPEED;
			else if(iResult == 1)
				eBot->v.velocity[1] -= BOT_MIN_SPEED;

			eBot->v.angles[1] = Math_VectorToYaw(eBot->v.velocity);
		}
		else if(rand()%150 == 0)
		{
			Monster_Jump(eBot,200.0f);

			Entity_Animate(eBot,PlayerAnimation_Jump);
		}
#endif
		break;
	case THINK_WANDERING:
		{
			edict_t		*eTarget;
			Waypoint_t	*wPoint;
//			Weapon_t	*wMyWeapon;
//			vec3_t		vAngle;

			eTarget = Monster_GetTarget(eBot);
			if(eTarget)
			{
				if(Monster_GetRelationship(eBot,eTarget) == RELATIONSHIP_HATE)
				{
					// [22/3/2013] Begin attacking next frame ~hogsy
					Monster_SetThink(eBot,THINK_ATTACKING);
					return;
				}
			}

			if(!eBot->monster.vTarget)
			{
				// [28/7/2012] TODO: Find specific waypoint such as an item ~hogsy
				wPoint = Waypoint_GetByVisibility(eBot->v.origin);
				if(wPoint)
				{
					if(wPoint->bOpen)
					{
						// [22/3/2013] TODO: Tell that current entity it's time to move... ~hogsy
					}

					Math_VectorCopy(wPoint->position,eBot->monster.vTarget);
				}
			}

#if 0
			wMyWeapon = Weapon_GetCurrentWeapon(eBot);
			if(MONSTER_GetRange(eBot,eBot->v.enemy->v.origin) > 4000)
				return;
			else if(wMyWeapon->iPrimaryType == AM_MELEE && MONSTER_GetRange(eBot,eBot->v.enemy->v.origin) > MONSTER_RANGE_MELEE)
				return;
			else if(Monster_IsVisible(eBot,eBot->v.enemy))
			{
				// [5/8/2012] No ammo and it's not a melee weapon? ~hogsy
				if(!Weapon_CheckPrimaryAmmo(eBot) && wMyWeapon->iPrimaryType != AM_MELEE)
				{
					// [5/8/2012] Should probably flee ~hogsy
					Monster_SetThink(eBot,THINK_FLEEING);
					return;
				}

				Math_VectorSubtract(eBot->v.enemy->v.origin,eBot->v.origin,vAngle);

		//		ent->v.ideal_yaw	= VectorToAngles(vAngle);

				ChangeYaw(eBot);
			}
#endif
		}
		break;
	}
}