示例#1
0
//-----------------------------------------------------------------------------
// Purpose: Deal with input
//-----------------------------------------------------------------------------
void C_VGuiScreen::ClientThink( void )
{
	int nButtonsChanged = m_nOldButtonState ^ m_nButtonState;

	m_nOldButtonState = m_nButtonState;

	// Debounced button codes for pressed/released
	// UNDONE: Do we need auto-repeat?
	m_nButtonPressed =  nButtonsChanged & m_nButtonState;		// The changed ones still down are "pressed"
	m_nButtonReleased = nButtonsChanged & (~m_nButtonState);	// The ones not down are "released"

	BaseClass::ClientThink();

	// FIXME: We should really be taking bob, shake, and roll into account
	// but if we did, then all the inputs would be generated multiple times
	// if the world was rendered multiple times (for things like water, etc.)

	vgui::Panel *pPanel = m_PanelWrapper.GetPanel();
	if (!pPanel)
		return;
	
	C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();
	if (!pLocalPlayer)
		return;

	// Generate a ray along the view direction
	Vector vecEyePosition = pLocalPlayer->EyePosition();
	
	QAngle viewAngles = pLocalPlayer->EyeAngles( );

	// Compute cursor position...
	Ray_t lookDir;
	Vector endPos;
	
	float u, v;

	// Viewmodel attached screens that take input need to have a moving cursor
	// Do a pick under the cursor as our selection
	Vector viewDir;
	AngleVectors( viewAngles, &viewDir );
	VectorMA( vecEyePosition, 1000.0f, viewDir, endPos );
	lookDir.Init( vecEyePosition, endPos );

	if (!IntersectWithRay( lookDir, &u, &v, NULL ))
		return;

	if ( ((u < 0) || (v < 0) || (u > 1) || (v > 1)) && !m_bLoseThinkNextFrame)
		return;

	// This will cause our panel to grab all input!
	g_pClientMode->ActivateInGameVGuiContext( pPanel );

	// Convert (u,v) into (px,py)
	int px = (int)(u * m_nPixelWidth + 0.5f);
	int py = (int)(v * m_nPixelHeight + 0.5f);

	// Generate mouse input commands
	if ((px != m_nOldPx) || (py != m_nOldPy))
	{
		g_InputInternal->InternalCursorMoved( px, py );
		m_nOldPx = px;
		m_nOldPy = py;
	}

	if (m_nButtonPressed & IN_ATTACK)
	{
		g_InputInternal->SetMouseCodeState( MOUSE_LEFT, vgui::BUTTON_PRESSED );
		g_InputInternal->InternalMousePressed(MOUSE_LEFT);
	}
	if (m_nButtonPressed & IN_ATTACK2)
	{
		g_InputInternal->SetMouseCodeState( MOUSE_RIGHT, vgui::BUTTON_PRESSED );
		g_InputInternal->InternalMousePressed( MOUSE_RIGHT );
	}
	if ( (m_nButtonReleased & IN_ATTACK) || m_bLoseThinkNextFrame) // for a button release on loosing focus
	{
		g_InputInternal->SetMouseCodeState( MOUSE_LEFT, vgui::BUTTON_RELEASED );
		g_InputInternal->InternalMouseReleased( MOUSE_LEFT );
	}
	if (m_nButtonReleased & IN_ATTACK2)
	{
		g_InputInternal->SetMouseCodeState( MOUSE_RIGHT, vgui::BUTTON_RELEASED );
		g_InputInternal->InternalMouseReleased( MOUSE_RIGHT );
	}

	if ( m_bLoseThinkNextFrame == true )
	{
		m_bLoseThinkNextFrame = false;
		SetNextClientThink( CLIENT_THINK_NEVER );
	}

	g_pClientMode->DeactivateInGameVGuiContext( );
}
示例#2
0
static qboolean InitFlyby(player_state_t *self, player_state_t *player, int checkvis)
{
	float	f, maxlen;
	vec3_t	vec, vec2;
	vec3_t	forward, right, up;

	VectorCopy(player->viewangles, vec);
	vec[0] = 0;
	AngleVectors (vec, forward, right, up);
//	for (i = 0; i < 3; i++)
//		forward[i] *= 3;

	maxlen = 1000;
	VectorAdd(forward, up, vec2);
	VectorAdd(vec2, right, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	VectorAdd(forward, up, vec2);
	VectorSubtract(vec2, right, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	VectorAdd(forward, right, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	VectorSubtract(forward, right, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	VectorAdd(forward, up, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	VectorSubtract(forward, up, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	VectorAdd(up, right, vec2);
	VectorSubtract(vec2, forward, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	VectorSubtract(up, right, vec2);
	VectorSubtract(vec2, forward, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	// invert
	VectorNegate(forward, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	VectorCopy(forward, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	// invert
	VectorNegate(right, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	VectorCopy(right, vec2);

	if ((f = Cam_TryFlyby(self, player, vec2, checkvis)) < maxlen)
	{
		maxlen = f;
		VectorCopy(vec2, vec);
	}

	// ack, can't find him
	if (maxlen >= 1000)
	{
	//	Cam_Unlock();
		return false;
	}

	locked = true;
	VectorCopy(vec, desired_position);
	return true;
}
示例#3
0
文件: lightmap.c 项目: kevlund/ufoai
/**
 * @brief Create lights out of patches and entity lights
 * @sa LightWorld
 * @sa BuildPatch
 */
void BuildLights (void)
{
	int i;
	light_t *l;

	/* surfaces */
	for (i = 0; i < MAX_MAP_FACES; i++) {
		const patch_t *p = face_patches[i];
		while (p) {  /* iterate subdivided patches */
			if (VectorEmpty(p->light))
				continue;

			numlights[config.compile_for_day]++;
			l = Mem_AllocType(light_t);

			VectorCopy(p->origin, l->origin);

			l->next = lights[config.compile_for_day];
			lights[config.compile_for_day] = l;

			l->type = emit_surface;

			l->intensity = ColorNormalize(p->light, l->color);
			l->intensity *= p->area * config.surface_scale;

			p = p->next;
		}
	}

	/* entities (skip the world) */
	for (i = 1; i < num_entities; i++) {
		float intensity;
		const char *color;
		const char *target;
		const entity_t *e = &entities[i];
		const char *name = ValueForKey(e, "classname");
		if (!Q_strstart(name, "light"))
			continue;

		/* remove those lights that are only for the night version */
		if (config.compile_for_day) {
			const int spawnflags = atoi(ValueForKey(e, "spawnflags"));
			if (!(spawnflags & 1))	/* day */
				continue;
		}

		numlights[config.compile_for_day]++;
		l = Mem_AllocType(light_t);

		GetVectorForKey(e, "origin", l->origin);

		/* link in */
		l->next = lights[config.compile_for_day];
		lights[config.compile_for_day] = l;

		intensity = FloatForKey(e, "light");
		if (!intensity)
			intensity = 300.0;
		color = ValueForKey(e, "_color");
		if (color && color[0] != '\0'){
			if (sscanf(color, "%f %f %f", &l->color[0], &l->color[1], &l->color[2]) != 3)
				Sys_Error("Invalid _color entity property given: %s", color);
			ColorNormalize(l->color, l->color);
		} else
			VectorSet(l->color, 1.0, 1.0, 1.0);
		l->intensity = intensity * config.entity_scale;
		l->type = emit_point;

		target = ValueForKey(e, "target");
		if (target[0] != '\0' || Q_streq(name, "light_spot")) {
			l->type = emit_spotlight;
			l->stopdot = FloatForKey(e, "_cone");
			if (!l->stopdot)
				l->stopdot = 10;
			l->stopdot = cos(l->stopdot * torad);
			if (target[0] != '\0') {	/* point towards target */
				entity_t *e2 = FindTargetEntity(target);
				if (!e2)
					Com_Printf("WARNING: light at (%i %i %i) has missing target '%s' - e.g. create an info_null that has a 'targetname' set to '%s'\n",
						(int)l->origin[0], (int)l->origin[1], (int)l->origin[2], target, target);
				else {
					vec3_t dest;
					GetVectorForKey(e2, "origin", dest);
					VectorSubtract(dest, l->origin, l->normal);
					VectorNormalize(l->normal);
				}
			} else {	/* point down angle */
				const float angle = FloatForKey(e, "angle");
				if (angle == ANGLE_UP) {
					l->normal[0] = l->normal[1] = 0.0;
					l->normal[2] = 1.0;
				} else if (angle == ANGLE_DOWN) {
					l->normal[0] = l->normal[1] = 0.0;
					l->normal[2] = -1.0;
				} else {
					l->normal[2] = 0;
					l->normal[0] = cos(angle * torad);
					l->normal[1] = sin(angle * torad);
				}
			}
		}
	}

	/* handle worldspawn light settings */
	{
		const entity_t *e = &entities[0];
		const char *ambient, *light, *angles, *color;
		float f;
		int i;

		if (config.compile_for_day) {
			ambient = ValueForKey(e, "ambient_day");
			light = ValueForKey(e, "light_day");
			angles = ValueForKey(e, "angles_day");
			color = ValueForKey(e, "color_day");
		} else {
			ambient = ValueForKey(e, "ambient_night");
			light = ValueForKey(e, "light_night");
			angles = ValueForKey(e, "angles_night");
			color = ValueForKey(e, "color_night");
		}

		if (light[0] != '\0')
			sun_intensity = atoi(light);

		if (angles[0] != '\0') {
			VectorClear(sun_angles);
			if (sscanf(angles, "%f %f", &sun_angles[0], &sun_angles[1]) != 2)
				Sys_Error("wrong angles values given: '%s'", angles);
			AngleVectors(sun_angles, sun_normal, NULL, NULL);
		}

		if (color[0] != '\0') {
			GetVectorFromString(color, sun_color);
			ColorNormalize(sun_color, sun_color);
		}

		if (ambient[0] != '\0')
			GetVectorFromString(ambient, sun_ambient_color);

		/* optionally pull brightness from worldspawn */
		f = FloatForKey(e, "brightness");
		if (f > 0.0)
			config.brightness = f;

		/* saturation as well */
		f = FloatForKey(e, "saturation");
		if (f > 0.0)
			config.saturation = f;
		else
			Verb_Printf(VERB_EXTRA, "Invalid saturation setting (%f) in worldspawn found\n", f);

		f = FloatForKey(e, "contrast");
		if (f > 0.0)
			config.contrast = f;
		else
			Verb_Printf(VERB_EXTRA, "Invalid contrast setting (%f) in worldspawn found\n", f);

		/* lightmap resolution downscale (e.g. 4 = 1 << 4) */
		i = atoi(ValueForKey(e, "quant"));
		if (i >= 1 && i <= 6)
			config.lightquant = i;
		else
			Verb_Printf(VERB_EXTRA, "Invalid quant setting (%i) in worldspawn found\n", i);
	}

	Verb_Printf(VERB_EXTRA, "light settings:\n * intensity: %i\n * sun_angles: pitch %f yaw %f\n * sun_color: %f:%f:%f\n * sun_ambient_color: %f:%f:%f\n",
		sun_intensity, sun_angles[0], sun_angles[1], sun_color[0], sun_color[1], sun_color[2], sun_ambient_color[0], sun_ambient_color[1], sun_ambient_color[2]);
	Verb_Printf(VERB_NORMAL, "%i direct lights for %s lightmap\n", numlights[config.compile_for_day], (config.compile_for_day ? "day" : "night"));
}
void C_ParticleSmokeGrenade::Update(float fTimeDelta)
{
	m_LifetimeCounter += fTimeDelta;
	
	// Update the smoke trail.
	C_BaseEntity *pAimEnt = GetFollowedEntity();
	if ( pAimEnt )
	{
		Vector forward, right, up;

		// Update the smoke particle color.
		if(m_CurrentStage == 0)
		{
			m_SmokeTrail.m_StartColor = EngineGetLightForPoint(GetAbsOrigin()) * 0.5f;
			m_SmokeTrail.m_EndColor = m_SmokeTrail.m_StartColor;
		}

		// Spin the smoke trail.
		AngleVectors(pAimEnt->GetAbsAngles(), &forward, &right, &up);
		m_SmokeTrail.m_VelocityOffset = forward * 30 + GetAbsVelocity();

		m_SmokeTrail.SetLocalOrigin( GetAbsOrigin() );
		m_SmokeTrail.Update(fTimeDelta);
	}	
	
	
	// Update our fade alpha.
	if(m_LifetimeCounter < m_FadeStartTime)
	{
		m_FadeAlpha = 1;
	}
	else if(m_LifetimeCounter < m_FadeEndTime)
	{
		float fadePercent = (m_LifetimeCounter - m_FadeStartTime) / (m_FadeEndTime - m_FadeStartTime);
		m_FadeAlpha = cos(fadePercent * 3.14159) * 0.5 + 0.5;
	}
	else
	{
		m_FadeAlpha = 0;
	}

	// Scale by the amount the sphere has grown.
	m_FadeAlpha *= m_ExpandRadius / SMOKESPHERE_MAX_RADIUS;

	if(m_CurrentStage == 1)
	{
		// Update the expanding sphere.
		m_ExpandTimeCounter += fTimeDelta;
		if(m_ExpandTimeCounter > SMOKESPHERE_EXPAND_TIME)
			m_ExpandTimeCounter = SMOKESPHERE_EXPAND_TIME;

		m_ExpandRadius = SMOKESPHERE_MAX_RADIUS * (float)sin(m_ExpandTimeCounter * 3.14159265358 * 0.5 / SMOKESPHERE_EXPAND_TIME);

		// Add our influence to the global smoke fog alpha.
		float testDist = (EngineGetVecRenderOrigin() - m_SmokeBasePos).Length();
		float fadeEnd = m_ExpandRadius * 0.75;
		if(testDist < fadeEnd)
		{
			EngineGetSmokeFogOverlayAlpha() += 1 - testDist / fadeEnd;
		}	


		// This is used to randomize the direction it chooses to move a particle in.
		int offsetLookup[3] = {-1,0,1};

		// Update all the moving traders and establish new ones.
		int nTotal = m_xCount * m_yCount * m_zCount;
		for(int i=0; i < nTotal; i++)
		{
			SmokeParticleInfo *pInfo = &m_SmokeParticleInfos[i];

			if(!pInfo->m_pParticle)
				continue;
		
			if(pInfo->m_TradeIndex == -1)
			{
				pInfo->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha;
				pInfo->m_pParticle->m_Color[0] = pInfo->m_Color[0];
				pInfo->m_pParticle->m_Color[1] = pInfo->m_Color[1];
				pInfo->m_pParticle->m_Color[2] = pInfo->m_Color[2];

				// Is there an adjacent one that's not trading?
				int x, y, z;
				GetParticleInfoXYZ(i, x, y, z);

				int xCountOffset = rand();
				int yCountOffset = rand();
				int zCountOffset = rand();

				bool bFound = false;
				for(int xCount=0; xCount < 3 && !bFound; xCount++)
				{
					for(int yCount=0; yCount < 3 && !bFound; yCount++)
					{
						for(int zCount=0; zCount < 3; zCount++)
						{
							int testX = x + offsetLookup[(xCount+xCountOffset) % 3];
							int testY = y + offsetLookup[(yCount+yCountOffset) % 3];
							int testZ = z + offsetLookup[(zCount+zCountOffset) % 3];

							if(testX == x && testY == y && testZ == z)
								continue;

							if(IsValidXYZCoords(testX, testY, testZ))
							{
								SmokeParticleInfo *pOther = GetSmokeParticleInfo(testX, testY, testZ);
								if(pOther->m_pParticle && pOther->m_TradeIndex == -1)
								{
									// Ok, this one is looking to trade also.
									pInfo->m_TradeIndex = GetSmokeParticleIndex(testX, testY, testZ);
									pOther->m_TradeIndex = i;
									pInfo->m_TradeClock = pOther->m_TradeClock = 0;
									pInfo->m_TradeDuration = FRand(TRADE_DURATION_MIN, TRADE_DURATION_MAX);
									
									bFound = true;
									break;
								}
							}
						}
					}
				}
			}
			else
			{
				SmokeParticleInfo *pOther = &m_SmokeParticleInfos[pInfo->m_TradeIndex];
				assert(pOther->m_TradeIndex == i);
				
				// This makes sure the trade only gets updated once per frame.
				if(pInfo < pOther)
				{
					// Increment the trade clock..
					pInfo->m_TradeClock = (pOther->m_TradeClock += fTimeDelta);
					int x, y, z;
					GetParticleInfoXYZ(i, x, y, z);
					Vector myPos = GetSmokeParticlePos(x, y, z);
					
					int otherX, otherY, otherZ;
					GetParticleInfoXYZ(pInfo->m_TradeIndex, otherX, otherY, otherZ);
					Vector otherPos = GetSmokeParticlePos(otherX, otherY, otherZ);

					// Is the trade finished?
					if(pInfo->m_TradeClock >= pInfo->m_TradeDuration)
					{
						pInfo->m_TradeIndex = pOther->m_TradeIndex = -1;
						
						pInfo->m_pParticle->m_Pos = otherPos;
						pOther->m_pParticle->m_Pos = myPos;

						SmokeGrenadeParticle *temp = pInfo->m_pParticle;
						pInfo->m_pParticle = pOther->m_pParticle;
						pOther->m_pParticle = temp;
					}
					else
					{			
						// Ok, move them closer.
						float percent = (float)cos(pInfo->m_TradeClock * 2 * 1.57079632f / pInfo->m_TradeDuration);
						percent = percent * 0.5 + 0.5;
						
						pInfo->m_pParticle->m_FadeAlpha  = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * (1 - percent);
						pOther->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * percent;

						InterpColor(pInfo->m_pParticle->m_Color,  pInfo->m_Color, pOther->m_Color, 1-percent);
						InterpColor(pOther->m_pParticle->m_Color, pInfo->m_Color, pOther->m_Color, percent);

						pInfo->m_pParticle->m_Pos  = myPos + (otherPos - myPos) * (1 - percent);
						pOther->m_pParticle->m_Pos = myPos + (otherPos - myPos) * percent;
					}
				}
			}
		}
	}
}
/*
===============
CG_AttachmentDir

Return the attachment direction
===============
*/
bool CG_AttachmentDir( attachment_t *a, vec3_t v )
{
	vec3_t    forward;
	centity_t *cent;

	if ( !a )
	{
		return false;
	}

	switch ( a->type )
	{
		case AT_STATIC:
			return false;

		case AT_TAG:
			if ( !a->tagValid )
			{
				return false;
			}

			VectorCopy( a->re.axis[ 0 ], v );
			break;

		case AT_CENT:
			if ( !a->centValid )
			{
				return false;
			}

			cent = &cg_entities[ a->centNum ];
			AngleVectors( cent->lerpAngles, forward, nullptr, nullptr );
			VectorCopy( forward, v );
			break;

		case AT_PARTICLE:
			if ( !a->particleValid )
			{
				return false;
			}

			if ( !a->particle->valid )
			{
				a->particleValid = false;
				return false;
			}
			else
			{
				VectorCopy( a->particle->velocity, v );
			}

			break;

		default:
			CG_Printf( S_ERROR "Invalid attachmentType_t in attachment\n" );
			break;
	}

	VectorNormalize( v );
	return true;
}
示例#6
0
void p_berserk_attack (edict_t *ent, int move_state)
{
	int		punch_dmg = BERSERK_PUNCH_INITIAL_DAMAGE + BERSERK_PUNCH_ADDON_DAMAGE * ent->myskills.abilities[BERSERK].current_level;
	int		slash_dmg = BERSERK_SLASH_INITIAL_DAMAGE + BERSERK_SLASH_ADDON_DAMAGE * ent->myskills.abilities[BERSERK].current_level;
	int		crush_dmg = BERSERK_CRUSH_INITIAL_DAMAGE + BERSERK_CRUSH_ADDON_DAMAGE * ent->myskills.abilities[BERSERK].current_level;
	vec3_t	forward, right, up, angles;

	ent->client->idle_frames = 0;
	AngleVectors(ent->s.angles, NULL, right, up);
	AngleVectors(ent->client->v_angle, forward, NULL, NULL);
	VectorCopy(ent->client->v_angle, angles);
	
	if (move_state == BERSERK_RUN_FORWARD)
	{
		G_RunFrames(ent, BERSERK_FRAMES_RUNATTACK1_START, BERSERK_FRAMES_RUNATTACK1_END, false);

		// swing left-right
		if (ent->s.frame == 124)
		{
			angles[YAW] += 20;
			AngleCheck(&angles[YAW]);
			AngleVectors(angles, forward, NULL, NULL);

			p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH);
		}
		else if (ent->s.frame == 125)
		{
			p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH);
		}
		else if (ent->s.frame == 126)
		{
			angles[YAW] -= 20;
			AngleCheck(&angles[YAW]);
			AngleVectors(angles, forward, NULL, NULL);

			p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH);
		}
	}
	else if (move_state == BERSERK_RUN_BACKWARD)
	{
		G_RunFrames(ent, BERSERK_FRAMES_RUNATTACK1_START, BERSERK_FRAMES_RUNATTACK1_END, true);

		// swing left-right
		if (ent->s.frame == 124)
		{
			angles[YAW] += 20;
			AngleCheck(&angles[YAW]);
			AngleVectors(angles, forward, NULL, NULL);

			p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH);
		}
		else if (ent->s.frame == 125)
		{
			p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH);
		}
		else if (ent->s.frame == 126)
		{
			angles[YAW] -= 20;
			AngleCheck(&angles[YAW]);
			AngleVectors(angles, forward, NULL, NULL);

			p_berserk_melee(ent, forward, NULL, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH);
		}
	}
	else if (ent->client->weapon_mode == 1)	// slash
	{
		G_RunFrames(ent, BERSERK_FRAMES_SLASH_START, BERSERK_FRAMES_SLASH_END, false);

		if ((ent->s.frame == 79) || (ent->s.frame == 80))
			p_berserk_melee(ent, forward, up, slash_dmg, BERSERK_SLASH_KNOCKBACK, BERSERK_SLASH_RANGE, MOD_BERSERK_SLASH);
	}
	else if (ent->client->weapon_mode == 2)	// crush
	{
		G_RunFrames(ent, BERSERK_FRAMES_SLAM_START, BERSERK_FRAMES_SLAM_END, false);

		if (ent->s.frame == 154)
			p_berserk_crush(ent, crush_dmg, BERSERK_CRUSH_RANGE, MOD_BERSERK_CRUSH);
	}
	else // punch
	{
		G_RunFrames(ent, BERSERK_FRAMES_PUNCH_START, BERSERK_FRAMES_PUNCH_END, false);
		
		// swing left-right
		if (ent->s.frame == 66)
		{
			angles[YAW] += 20;//45;
			AngleCheck(&angles[YAW]);
			AngleVectors(angles, forward, NULL, NULL);

			p_berserk_melee(ent, forward, right, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH);
		}
		else if (ent->s.frame == 67)
		{
			p_berserk_melee(ent, forward, right, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH);
		}
		else if (ent->s.frame == 68)
		{
			angles[YAW] -= 20;//45;
			AngleCheck(&angles[YAW]);
			AngleVectors(angles, forward, NULL, NULL);

			p_berserk_melee(ent, forward, right, punch_dmg, BERSERK_PUNCH_KNOCKBACK, BERSERK_PUNCH_RANGE, MOD_BERSERK_PUNCH);
		}
	}

	p_berserk_swing(ent);
}
示例#7
0
void EjectShell (edict_t *self, vec3_t start, int toggle )
{
	edict_t *shell;
	vec3_t  forward, right, up;
	float           r;
	float           fix = 1.0;
		int left = 0;

	if (sv_shelloff->value)
		return;
	
	shell = G_Spawn();
	++shells;

	AngleVectors (self->client->v_angle, forward, right, up);

	if (self->client->pers.hand == LEFT_HANDED)
		{
			left = 1;
			fix = -1.0;
		}
	else if ( self->client->pers.hand == CENTER_HANDED)
		fix = 0;


		// zucc spent a fair amount of time hacking these until they look ok,
		// several of them could be improved however.

	if (self->client->curr_weap == MK23_NUM )
	{
				VectorMA (start, left?-7:.4, right, start);
		VectorMA (start, left?5:2, forward, start);
		VectorMA (start, left?-10:-8 , up, start);
	}               
	else if (self->client->curr_weap == M4_NUM)
	{               
				VectorMA (start, left?-10:5, right, start);
		VectorMA (start, left?6:12, forward, start);
		VectorMA (start, left?-9:-11, up, start);
	}
	else if (self->client->curr_weap == MP5_NUM)
	{
				VectorMA (start, left?-10:6, right, start);
		VectorMA (start, left?6:8, forward, start);
		VectorMA (start, left?-9:-10, up, start);
	}
	else if (self->client->curr_weap == SNIPER_NUM)
	{
		VectorMA (start, fix*11, right, start);
		VectorMA (start, 2, forward, start);
		VectorMA (start, -11, up, start);
		
	}
		else if (self->client->curr_weap == M3_NUM)
		{
				VectorMA(start, left?-9:3, right, start);
				VectorMA(start, left?4:4, forward, start);
				VectorMA(start, left?-1:-1, up, start);
		}
	
		else if (self->client->curr_weap == DUAL_NUM)
	{
			   if (self->client->pers.hand == LEFT_HANDED)
					VectorMA (start, ((toggle==1)?8:-8), right, start);
	       else
					VectorMA (start, ((toggle==1)?-4:4), right, start);
			   VectorMA (start, 6, forward, start);
	       VectorMA (start, -9, up, start);
		
	}


	if ( (forward[2] >= -1) && (forward[2] < -0.99) ) {   
		VectorMA (start, 5, forward, start);
		VectorMA (start, -0.5, up, start); }

	else if ( (forward[2] >= -0.99) && (forward[2] < -0.98) ) {   
		VectorMA (start, 5, forward, start);
		VectorMA (start, -.1, up, start); }
	else if ( (forward[2] >= -0.98) && (forward[2] < -0.97) ) {   
		VectorMA (start, 5.1, forward, start);
		VectorMA (start, 0.3, up, start); }
	else if ( (forward[2] >= -0.97) && (forward[2] < -0.96) ) {   
		VectorMA (start, 5.2, forward, start);
		VectorMA (start, 0.7, up, start); }
	else if ( (forward[2] >= -0.96) && (forward[2] < -0.95) ) {   
		VectorMA (start, 5.2, forward, start);
		VectorMA (start, 1.1, up, start); }
	else if ( (forward[2] >= -0.95) && (forward[2] < -0.94) ) {   
		VectorMA (start, 5.3, forward, start);
		VectorMA (start, 1.5, up, start); }
	else if ( (forward[2] >= -0.94) && (forward[2] < -0.93) ) {   
		VectorMA (start, 5.4, forward, start);
		VectorMA (start, 1.9, up, start); }
	else if ( (forward[2] >= -0.93) && (forward[2] < -0.92) ) {   
		VectorMA (start, 5.5, forward, start);
		VectorMA (start, 2.3, up, start); }
	else if ( (forward[2] >= -0.92) && (forward[2] < -0.91) ) {   
		VectorMA (start, 5.6, forward, start);
		VectorMA (start, 2.7, up, start); }
	else if ( (forward[2] >= -0.91) && (forward[2] < -0.9) ) {   
		VectorMA (start, 5.7, forward, start);
		VectorMA (start, 3.1, up, start); }

	else if ( (forward[2] >= -0.9) && (forward[2] < -0.85) ) {   
		VectorMA (start, 5.8, forward, start);
		VectorMA (start, 3.5, up, start); }
	else if ( (forward[2] >= -0.85) && (forward[2] < -0.8) ) {   
		VectorMA (start, 6, forward, start);
		VectorMA (start, 4, up, start); }
	else if ( (forward[2] >= -0.8) && (forward[2] < -0.6) ) {   
		VectorMA (start, 6.5, forward, start);
		VectorMA (start, 4.5, up , start); }
	else if ( (forward[2] >= -0.6) && (forward[2] < -0.4) ) {   
		VectorMA (start, 8, forward, start);
		VectorMA (start, 5.5, up , start); }
	else if ( (forward[2] >= -0.4) && (forward[2] < -0.2) ) {   
		VectorMA (start, 9.5, forward, start);
		VectorMA (start, 6, up , start); }
	else if ( (forward[2] >= -0.2) && (forward[2] < 0) ) {   
		VectorMA (start, 11, forward, start);
		VectorMA (start, 6.5, up , start); }
	else if ( (forward[2] >= 0) && (forward[2] < 0.2) ) {   
		VectorMA (start, 12, forward, start);
		VectorMA (start, 7, up, start); }
	else if ( (forward[2] >= 0.2) && (forward[2] < 0.4) ) {   
		VectorMA (start, 14, forward, start);
		VectorMA (start, 6.5, up, start); }
	else if ( (forward[2] >= 0.4) && (forward[2] < 0.6) ) {   
		VectorMA (start, 16, forward, start);
		VectorMA (start, 6, up, start); }
	else if ( (forward[2] >= 0.6) && (forward[2] < 0.8) ) {   
		VectorMA (start, 18, forward, start);
		VectorMA (start, 5, up, start); }
	else if ( (forward[2] >= 0.8) && (forward[2] < 0.85) ) {   
		VectorMA (start, 18, forward, start);
		VectorMA (start, 4, up, start); }
	else if ( (forward[2] >= 0.85) && (forward[2] < 0.9) ) {   
		VectorMA (start, 18, forward, start);
		VectorMA (start, 2.5, up, start); }

	else if ( (forward[2] >= 0.9) && (forward[2] < 0.91) ) {   
		VectorMA (start, 18.2, forward, start);
		VectorMA (start, 2.2, up, start); }
	else if ( (forward[2] >= 0.91) && (forward[2] < 0.92) ) {   
		VectorMA (start, 18.4, forward, start);
		VectorMA (start, 1.9, up, start); }
	else if ( (forward[2] >= 0.92) && (forward[2] < 0.93) ) {   
		VectorMA (start, 18.6, forward, start);
		VectorMA (start, 1.6, up, start); }
	else if ( (forward[2] >= 0.93) && (forward[2] < 0.94) ) {   
		VectorMA (start, 18.8, forward, start);
		VectorMA (start, 1.3, up, start); }
	else if ( (forward[2] >= 0.94) && (forward[2] < 0.95) ) {   
		VectorMA (start, 19, forward, start);
		VectorMA (start, 1, up, start); }
	else if ( (forward[2] >= 0.95) && (forward[2] < 0.96) ) {   
		VectorMA (start, 19.2, forward, start);
		VectorMA (start, 0.7, up, start); }
	else if ( (forward[2] >= 0.96) && (forward[2] < 0.97) ) {   
		VectorMA (start, 19.4, forward, start);
		VectorMA (start, 0.4, up, start); }
	else if ( (forward[2] >= 0.97) && (forward[2] < 0.98) ) {   
		VectorMA (start, 19.6, forward, start);
		VectorMA (start, -0.2, up, start); }
	else if ( (forward[2] >= 0.98) && (forward[2] < 0.99) ) {   
		VectorMA (start, 19.8, forward, start);
		VectorMA (start, -0.6, up, start); }

	else if ( (forward[2] >= 0.99) && (forward[2] <= 1) ) {   
		VectorMA (start, 20, forward, start); 
		VectorMA (start, -1, up , start); }

	VectorCopy (start , shell->s.origin);
	if (fix == 0) // we want some velocity on those center handed ones
		fix = 1;
	if (self->client->curr_weap == SNIPER_NUM)
			VectorMA (shell->velocity, fix*(-35 + random() * -60), right, shell->velocity);
	    else if ( self->client->curr_weap == DUAL_NUM)
		{
			if (self->client->pers.hand == LEFT_HANDED)
				VectorMA (shell->velocity, (toggle==1?1:-1)*(35 + random() * 60), right, shell->velocity);
			else
				VectorMA (shell->velocity, (toggle==1?-1:1)*(35 + random() * 60), right, shell->velocity);
		}
		else
			VectorMA (shell->velocity, fix*(35 + random() * 60), right, shell->velocity);
	VectorMA (shell->avelocity, 500, right, shell->avelocity);
	if (self->client->curr_weap == SNIPER_NUM)
		VectorMA (shell->velocity, 60 + 40, up, shell->velocity);
	else
		VectorMA (shell->velocity, 60 + random() * 90, up, shell->velocity);

	shell->movetype = MOVETYPE_BOUNCE;
	shell->solid = SOLID_BBOX;

	if (self->client->curr_weap == M3_NUM)
		shell->s.modelindex = gi.modelindex ("models/weapons/shell/tris2.md2");
	else if (self->client->curr_weap == SNIPER_NUM)
		shell->s.modelindex = gi.modelindex ("models/weapons/shell/tris3.md2");
	else
		shell->s.modelindex = gi.modelindex ("models/weapons/shell/tris.md2");

	r = random();
	if (r < 0.1)
		shell->s.frame = 0;
	else if (r < 0.2)
		shell->s.frame = 1;
	else if (r < 0.3)
		shell->s.frame = 2;
	else if (r < 0.5)
		shell->s.frame = 3;
	else if (r < 0.6)
		shell->s.frame = 4;
	else if (r < 0.7)
		shell->s.frame = 5;
	else if (r < 0.8)
		shell->s.frame = 6;
	else if (r < 0.9)
		shell->s.frame = 7;
	else 
		shell->s.frame = 8;
		
	shell->owner = self;
	shell->touch = ShellTouch;
	shell->nextthink = level.time + 1.2 - (shells * .05);
	shell->think = ShellDie;
	shell->classname = "shell";



	gi.linkentity (shell);
}
示例#8
0
static void CG_OffsetThirdPersonView(void)
{
	vec3_t		forward, right, up;
	vec3_t		view;
	vec3_t		focusAngles;
	trace_t		trace;
	static vec3_t	mins = { -4, -4, -4 };
	static vec3_t	maxs = { 4, 4, 4 };
	vec3_t		focusPoint;
	float		focusDist;
	float		forwardScale, sideScale;

	cg.refdef.vieworg[2] += cg.predictedPlayerState.viewheight;

	VectorCopy(cg.refdefViewAngles, focusAngles);

	// if dead, look at killer
	if (cg.predictedPlayerState.stats[STAT_HEALTH] <= 0) {
		focusAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW];
		cg.refdefViewAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW];
	}

	if (focusAngles[PITCH] > 45) {
		focusAngles[PITCH] = 45;		// don't go too far overhead
	}
	AngleVectors(focusAngles, forward, NULL, NULL);

	VectorMA(cg.refdef.vieworg, FOCUS_DISTANCE, forward, focusPoint);

	VectorCopy(cg.refdef.vieworg, view);

	view[2] += 8;

	cg.refdefViewAngles[PITCH] *= 0.5;

	AngleVectors(cg.refdefViewAngles, forward, right, up);

	forwardScale = cos(cg_thirdPersonAngle.value / 180 * M_PI);
	sideScale = sin(cg_thirdPersonAngle.value / 180 * M_PI);
	VectorMA(view, -cg_thirdPersonRange.value * forwardScale, forward, view);
	VectorMA(view, -cg_thirdPersonRange.value * sideScale, right, view);

	// trace a ray from the origin to the viewpoint to make sure the view isn't
	// in a solid block.  Use an 8 by 8 block to prevent the view from near clipping anything

	if (!cg_cameraMode.integer) {
		CG_Trace(&trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID);

		if (trace.fraction != 1.0) {
			VectorCopy(trace.endpos, view);
			view[2] += (1.0 - trace.fraction) * 32;
			// try another trace to this position, because a tunnel may have the ceiling
			// close enough that this is poking out

			CG_Trace(&trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID);
			VectorCopy(trace.endpos, view);
		}
	}


	VectorCopy(view, cg.refdef.vieworg);

	// select pitch to look at focus point from vieword
	VectorSubtract(focusPoint, cg.refdef.vieworg, focusPoint);
	focusDist = sqrt(focusPoint[0] * focusPoint[0] + focusPoint[1] * focusPoint[1]);
	if (focusDist < 1) {
		focusDist = 1;	// should never happen
	}
	cg.refdefViewAngles[PITCH] = -180 / M_PI * atan2(focusPoint[2], focusDist);
	cg.refdefViewAngles[YAW] -= cg_thirdPersonAngle.value;
}
示例#9
0
static void CG_OffsetFirstPersonView(void)
{
	float			*origin;
	float			*angles;
	float			delta;
	float			f;
	int				timeDelta;
	
	if (cg.snap->ps.pm_type == PM_INTERMISSION) {
		return;
	}

	origin = cg.refdef.vieworg;
	angles = cg.refdefViewAngles;

	// if dead, fix the angle and don't add any kick
	if (cg.snap->ps.stats[STAT_HEALTH] <= 0) {
		angles[ROLL] = 40;
		angles[PITCH] = -15;
		angles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW];
		origin[2] += cg.predictedPlayerState.viewheight;
		return;
	}

	// add view height
	origin[2] += cg.predictedPlayerState.viewheight;

	// smooth out duck height changes
	timeDelta = cg.time - cg.duckTime;
	if (timeDelta < DUCK_TIME) {
		cg.refdef.vieworg[2] -= cg.duckChange 
			* (DUCK_TIME - timeDelta) / DUCK_TIME;
	}

	// add fall height
	delta = cg.time - cg.landTime;
	if (delta < LAND_DEFLECT_TIME) {
		f = delta / LAND_DEFLECT_TIME;
		cg.refdef.vieworg[2] += cg.landChange * f;
	} else if (delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME) {
		delta -= LAND_DEFLECT_TIME;
		f = 1.0 - (delta / LAND_RETURN_TIME);
		cg.refdef.vieworg[2] += cg.landChange * f;
	}

	// add step offset
	CG_StepOffset();

	// pivot the eye based on a neck length
#if 0
	{
#define	NECK_LENGTH		8
	vec3_t			forward, up;
 
	cg.refdef.vieworg[2] -= NECK_LENGTH;
	AngleVectors(cg.refdefViewAngles, forward, NULL, up);
	VectorMA(cg.refdef.vieworg, 3, forward, cg.refdef.vieworg);
	VectorMA(cg.refdef.vieworg, NECK_LENGTH, up, cg.refdef.vieworg);
	}
#endif
}
示例#10
0
/*
 * Tests whether the player entity ent is visible from the point origin.
 */
qboolean SV_IsPlayerVisibleFromPoint( vec3_t origin, clientSnapshot_t *frame, sharedEntity_t *ent, vec3_t diff) {
	int      i,contents_mask,goal_ent,viewer_clnum,ent_clnum,tries;
	trace_t   tr;
	vec3_t   start,end,dir,entangles,angles,temp,forward;
	sharedEntity_t *viewer_ent;
	client_t *viewer_cl, *ent_cl;
	playerState_t *viewer_ps, *ent_ps;
	float pitch;

	viewer_clnum = frame->ps.clientNum; // get the client number of the viewer
	ent_clnum = ent->s.clientNum; // get the client number of the other player

	if (viewer_clnum == ent_clnum) { // in case the viewer is the player entity
		return qtrue; // we don't need to hide us from ourselves
	}

	viewer_ps = &frame->ps;
	ent_ps = SV_GameClientNum(ent_clnum);

	if (viewer_ps->pm_type != PM_NORMAL) { // if the viewer is dead or spectating
		return qtrue; // let every entity be visible
	}

	if (ent_ps->pm_type != PM_NORMAL || (ent->s.weapon == WP_NONE)) { // if the player entity is dead or spectating
		return qtrue;
	}

	viewer_cl = svs.clients+viewer_clnum; // get the client of the viewer
	ent_cl = svs.clients+ent_clnum; // get the client of the other player

//	if (viewer_clnum > ent_clnum) { // if viewer_clnum > ent_clnum, we have already tested whether ent_clnum is able to see viewer_clnum.
//		if (ent_cl->tracetimer[viewer_clnum] > sv.time) return qtrue; // and we could assume symmetry of SV_IsPlayerVisibleFromPoint
//	}

	if (viewer_cl->tracetimer[ent_clnum] > sv.time+MEMORY+10) { // if the sv.time has been reset
		viewer_cl->tracetimer[ent_clnum] = sv.time; // reset the tracetimer
	} else if (viewer_cl->tracetimer[ent_clnum] > (sv.time+MEMORY-10)) { // if we have recently seen this entity, we are lazy and assume it is still visible
		// Com_Printf(va("client: %i, seen: %i\n", ent_clnum, viewer_cl->tracetimer[ent_clnum]));
		return qtrue;
	}

	goal_ent = SV_NumForGentity(ent); // this might always be the same as ent_clnum
	viewer_ent = SV_GentityNum(viewer_clnum);
	contents_mask = CONTENTS_SOLID;// |CONTENTS_BODY will work for doors, but also for windows  |CONTENTS_PLAYERCLIP|CONTENTS_SOLID|CONTENTS_MOVER|CONTENTS_PLAYERCLIP

//	if (seen->v.movetype == MOVETYPE_PUSH ) { //don't cull doors and plats :(
//		return false;
//	}

//	if (sv_antiwallhack.value == 1)    //1 only check player models, 2 = check all ents
//	if (strcmp(pr_strings + seen->v.classname, "player"))
//	return qfalse;

	// get camera origin (according to \cg_drawdebug 1)
	start[0] = origin[0];
	start[1] = origin[1];
	start[2] = origin[2]+3.0f;
	VectorCopy(viewer_ps->viewangles, angles);
	AnglesNormalize180(angles);
	pitch = angles[PITCH];
	angles[PITCH] = 0;
	angles[ROLL] = 0;
	AngleVectors(angles, forward, NULL, NULL);
	VectorScale(forward, (pitch/3.5f), temp);
	VectorAdd( start, temp, start);

	// if there is sufficient distance between viewer and player entity, check if player entity is within viewer's field of vision
	VectorSubtract(ent->r.currentOrigin, start, dir);
//	VectorAdd(ent->r.currentOrigin,dir,diff);// fill diff
	VectorCopy(viewer_ent->s.pos.trBase,diff);// fill diff
	vectoangles(dir, entangles);
	dir[2]=0; // pretend, players are on the same level (the height should no be taken into account)
	if (VectorLength(dir) > 1024) {// if it is not within close range (x,y-wise, not z-wise)
		if (!InFieldOfVision(viewer_ps->viewangles, 60.f, entangles, ent_clnum)) {// If the player entity is not in the field of vision of the viewer
//			 Com_Printf( va("behind: %i  vorg: %f,%f,%f  vang: %f,%f,%f  eorg: %f,%f,%f  dir: %f,%f,%f  eang: %f,%f,%f  ent: %i\n", viewer_clnum,origin[0],origin[1],origin[2],viewer_ps->viewangles[0],viewer_ps->viewangles[1],viewer_ps->viewangles[2],ent->r.currentOrigin[0],ent->r.currentOrigin[1],ent->r.currentOrigin[2],dir[0],dir[1],dir[2],entangles[0],entangles[1],entangles[2],ent_clnum));
			return qtrue; // if the player entity is behind the viewer, abstain from any computations (and transmit the entity to hear sounds)
//		} else {
//			 Com_Printf( va("front: %i  vorg: %f,%f,%f  vang: %f,%f,%f  eorg: %f,%f,%f  dir: %f,%f,%f  eang: %f,%f,%f  ent: %i\n", viewer_clnum,origin[0],origin[1],origin[2],viewer_ps->viewangles[0],viewer_ps->viewangles[1],viewer_ps->viewangles[2],ent->r.currentOrigin[0],ent->r.currentOrigin[1],ent->r.currentOrigin[2],dir[0],dir[1],dir[2],entangles[0],entangles[1],entangles[2],ent_clnum));
		}
	}

	// aim straight at the head of the entity from our eyes
	end[0] = ent->r.currentOrigin[0];
	end[1] = ent->r.currentOrigin[1];
	end[2] = ent->r.currentOrigin[2]+ent->r.maxs[2];// "+3.0f" doesn't do it. "+ent->r.maxs[2]" is at the top of the BBox
	VectorCopy(ent_ps->viewangles, angles);
	AnglesNormalize180(angles);
	pitch = angles[PITCH];
	angles[PITCH] = 0;
	angles[ROLL] = 0;
	AngleVectors(angles, forward, NULL, NULL);
	VectorScale(forward, (pitch/3.5f), temp);
	VectorAdd( end, temp, end);



	memset (&tr, 0, sizeof(tr));
	tr.fraction = 1;

	// check the head
	SV_Trace(&tr, start, NULL, NULL, end, viewer_clnum, contents_mask, qfalse);
	// Com_Printf(va("client: %i, trace: %f\n", ent->s.clientNum, tr.fraction));
	if (tr.fraction == 1 || tr.entityNum==goal_ent) {// tr.fraction == 1 || if there is a line of sight to the entity
		viewer_cl->tracetimer[ent_clnum] = sv.time + MEMORY;// update the trace timer so the entity will be visible the next 200 time units
		return qtrue;// and signal the entity is visible
	}
	// Com_Printf(va("origin(%f %f %f) min(%f %f %f) max(%f %f %f)\n", start[0], start[1], start[2], mins[0],mins[1],mins[2],maxs[0],maxs[1],maxs[2]));

	// check the last good offset
	VectorAdd(ent->r.currentOrigin,viewer_cl->lasttrace[ent_clnum],end);
	SV_Trace(&tr, start, NULL, NULL, end, viewer_clnum, contents_mask, qfalse);
	// Com_Printf(va("client: %i, trace: %f\n", ent->s.clientNum, tr.fraction));
	if (tr.fraction == 1 || tr.entityNum==goal_ent) {// tr.fraction == 1 || if there is a line of sight to the entity
		viewer_cl->tracetimer[ent_clnum] = sv.time + MEMORY;// update the trace timer so the entity will be visible the next 200 time units
		return qtrue;// and signal the entity is visible
	}

	// random
	tries = (viewer_cl->tracetimer[ent_clnum]+(MEMORY*20) > sv.time)?8:2;// if we have seen an entity recently, we try hard to locate it again
	for (i=0; i<tries; i++) {// Even if the head is not visible, other body parts might be. Let's check a few randomly selected points
		end[0] = ent->r.currentOrigin[0] + offsetrandom(ent->r.mins[0], ent->r.maxs[0]);
		end[1] = ent->r.currentOrigin[1] + offsetrandom(ent->r.mins[1], ent->r.maxs[1]);
		end[2] = ent->r.currentOrigin[2] + offsetrandom(ent->r.mins[2], ent->r.maxs[2]+3.f);

		SV_Trace(&tr, start, NULL, NULL, end, viewer_clnum, contents_mask, qfalse);
		if (tr.fraction == 1 || tr.entityNum==goal_ent) {//  if there is a line of sight to the entity
			// Com_Printf(va("found ent in %i hits\n", i));
			viewer_cl->tracetimer[ent_clnum] = sv.time + MEMORY;// update the trace timer so the entity will be visible the next 200 time units
			VectorSubtract(end, ent->r.currentOrigin, viewer_cl->lasttrace[ent_clnum]);// remember the offset
			return qtrue;// and signal the entity is visible
		}
	}

	viewer_cl->lasttrace[ent_clnum][0] = offsetrandom(ent->r.mins[0], ent->r.maxs[0]);
	viewer_cl->lasttrace[ent_clnum][1] = offsetrandom(ent->r.mins[1], ent->r.maxs[1]);
	viewer_cl->lasttrace[ent_clnum][2] = offsetrandom(ent->r.mins[2], ent->r.maxs[2]+3.f);

	return (viewer_cl->tracetimer[ent_clnum] > sv.time);// returns true if the entity was visible within the last 200 time units
}
示例#11
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void UTIL_FindPositionInRadius( positioninradius_t &info, CBaseEntity *navMeshEnt )
{
	Vector vecDir, vecTest;
	trace_t tr;
	for(; info.m_vFan.y < 360 - info.m_fStepSize; info.m_vFan.y += info.m_fStepSize )
	{
		AngleVectors( info.m_vFan, &vecDir );

		vecTest = info.m_vStartPosition + vecDir * info.m_fRadius;

		Vector vEndPos;

#ifdef ENABLE_PYTHON
		if( RecastMgr().HasMeshes() )
		{

			vEndPos = NavMeshGetPositionNearestNavArea( vecTest, info.m_fBeneathLimit, 128.0f, navMeshEnt );
            if( vEndPos == vec3_origin )
                continue;
		}
		else
#endif // ENABLE_PYTHON
		{
			UTIL_TraceLine( vecTest, vecTest - Vector( 0, 0, MAX_TRACE_LENGTH ), MASK_SHOT, info.m_hIgnore.Get(), COLLISION_GROUP_NONE, &tr );
			if( tr.fraction == 1.0 )
				continue;
			vEndPos = tr.endpos;
		}
            
		if( info.m_bTestPosition )
		{
			// Test position
			vEndPos.z += -info.m_vMins.z + info.m_fZOffset;
			UTIL_TraceHull( vEndPos,
							vEndPos + Vector( 0, 0, 10 ),
							info.m_vMins,
							info.m_vMaxs,
							info.m_iMask,
							info.m_hIgnore.Get(),
							COLLISION_GROUP_NONE,
							&tr );

			if( tr.fraction == 1.0 )
			{
				info.m_vPosition = tr.endpos;
				info.m_bSuccess = true;
				info.m_vFan.y += info.m_fStepSize;
				return;   
			}
		}
		else
		{
			info.m_vPosition = vEndPos;
			info.m_vPosition.z += info.m_fZOffset;
			info.m_bSuccess = true;
			info.m_vFan.y += info.m_fStepSize;
			return;
		}
	}

	info.m_bSuccess = false;
}
示例#12
0
/**
 * @param[in] tile Tile to check (normally 0 - except in assembled maps)
 * @param[in] traceLine The start and stop vectors of the trace
 * @param[in] traceBox The box we shove through the world
 * @param[in] headnode if < 0 we are in a leaf node
 * @param[in] contentmask content flags the trace should stop at (see MASK_*)
 * @param[in] brushrejects brushes the trace should ignore (see MASK_*)
 * @param[in] origin center for rotating objects
 * @param[in] angles current rotation status (in degrees) for rotating objects
 * @param[in] rmaShift how much the object was shifted by the RMA process (needed for doors)
 * @param[in] fraction The furthest distance needed to trace before we stop.
 * @brief Handles offseting and rotation of the end points for moving and rotating entities
 * @sa CM_BoxTrace
 */
trace_t CM_HintedTransformedBoxTrace (MapTile& tile, const Line& traceLine, const AABB& traceBox, const int headnode, const int contentmask, const int brushrejects, const vec3_t origin, const vec3_t angles, const vec3_t rmaShift, const float fraction)
{
	vec3_t start_l, end_l;
	vec3_t forward, right, up;
	vec3_t temp;
	bool rotated;

	/* subtract origin offset */
	VectorSubtract(traceLine.start, origin, start_l);
	VectorSubtract(traceLine.stop, origin, end_l);

	/* rotate start and end into the models frame of reference */
	if (headnode != tile.box_headnode && VectorNotEmpty(angles)) {
		rotated = true;
	} else {
		rotated = false;
	}

	if (rotated) {
		AngleVectors(angles, forward, right, up);

		VectorCopy(start_l, temp);
		start_l[0] = DotProduct(temp, forward);
		start_l[1] = -DotProduct(temp, right);
		start_l[2] = DotProduct(temp, up);

		VectorCopy(end_l, temp);
		end_l[0] = DotProduct(temp, forward);
		end_l[1] = -DotProduct(temp, right);
		end_l[2] = DotProduct(temp, up);
	}

	/* When tracing through a model, we want to use the nodes, planes etc. as calculated by ufo2map.
	 * But nodes and planes have been shifted in case of an RMA. At least for doors we need to undo the shift. */
	if (VectorNotEmpty(origin)) {					/* only doors seem to have their origin set */
		VectorAdd(start_l, rmaShift, start_l);		/* undo the shift */
		VectorAdd(end_l, rmaShift, end_l);
	}

	/* sweep the box through the model */
	boxtrace_t traceData;
	traceData.init(&tile, contentmask, brushrejects, fraction);
	traceData.setLineAndBox(Line(start_l, end_l), traceBox);
	trace_t trace = TR_BoxTrace(traceData, Line(start_l, end_l), traceBox, headnode, fraction);
	trace.mapTile = tile.idx;

	if (rotated && trace.fraction != 1.0) {
		vec3_t a;
		/** @todo figure out how to do this with existing angles */
		VectorNegate(angles, a);
		AngleVectors(a, forward, right, up);

		VectorCopy(trace.plane.normal, temp);
		trace.plane.normal[0] = DotProduct(temp, forward);
		trace.plane.normal[1] = -DotProduct(temp, right);
		trace.plane.normal[2] = DotProduct(temp, up);
	}

	VectorInterpolation(traceLine.start, traceLine.stop, trace.fraction, trace.endpos);

	return trace;
}
void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate )
{
	if ( m_bState == false )
	{
		if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
		{
			ShutDownLightHandle();
		}

		return;
	}

	Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
	FlashlightState_t state;

	if ( m_hTargetEntity != NULL )
	{
		if ( m_bCameraSpace )
		{
			const QAngle &angles = GetLocalAngles();

			C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
			if( pPlayer )
			{
				const QAngle playerAngles = pPlayer->GetAbsAngles();
				
				Vector vPlayerForward, vPlayerRight, vPlayerUp;
				AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp );

            	matrix3x4_t	mRotMatrix;
				AngleMatrix( angles, mRotMatrix );

				VectorITransform( vPlayerForward, mRotMatrix, vForward );
				VectorITransform( vPlayerRight, mRotMatrix, vRight );
				VectorITransform( vPlayerUp, mRotMatrix, vUp );

				float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length();
				vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist;

				VectorNormalize( vForward );
				VectorNormalize( vRight );
				VectorNormalize( vUp );
			}
		}
		else
		{
			vForward = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
			VectorNormalize( vForward );

			// JasonM - unimplemented
			Assert (0);

			//Quaternion q = DirectionToOrientation( dir );


			//
			// JasonM - set up vRight, vUp
			//

//			VectorNormalize( vRight );
//			VectorNormalize( vUp );
		}
	}
	else
	{
		AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
	}

	state.m_fHorizontalFOVDegrees = m_flLightFOV;
	state.m_fVerticalFOVDegrees = m_flLightFOV;

	state.m_vecLightOrigin = vPos;
	BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation );

	state.m_fQuadraticAtten = 0.0;
	state.m_fLinearAtten = 100;
	state.m_fConstantAtten = 0.0f;
	state.m_Color[0] = m_LinearFloatLightColor.x;
	state.m_Color[1] = m_LinearFloatLightColor.y;
	state.m_Color[2] = m_LinearFloatLightColor.z;
	state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
	state.m_NearZ = m_flNearZ;
	state.m_FarZ = m_flFarZ;
	state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat();
	state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat();
	state.m_bEnableShadows = m_bEnableShadows;
	state.m_pSpotlightTexture = materials->FindTexture( m_SpotlightTextureName, TEXTURE_GROUP_OTHER, false );
	state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;

	state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality

	if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE )
	{
		m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state );
	}
	else
	{
		if ( m_hTargetEntity != NULL || bForceUpdate == true )
		{
			g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
		}
	}

	if( m_bLightOnlyTarget )
	{
		g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity );
	}
	else
	{
		g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL );
	}

	g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );

	if ( bForceUpdate == false )
	{
		g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
	}
}
示例#14
0
//-----------------------------------------------------------------------------
//
// Look for vgui screens, returns true if it found one ...
//
//-----------------------------------------------------------------------------
C_BaseEntity *FindNearbyVguiScreen( const Vector &viewPosition, const QAngle &viewAngle, int nTeam )
{
	if ( IsX360() )
	{
		// X360TBD: Turn this on if feature actually used
		return NULL;
	}

	C_BasePlayer *pLocalPlayer = C_BasePlayer::GetLocalPlayer();

	Assert( pLocalPlayer );

	if ( !pLocalPlayer )
		return NULL;

	// Get the view direction...
	Vector lookDir;
	AngleVectors( viewAngle, &lookDir );

	// Create a ray used for raytracing 
	Vector lookEnd;
	VectorMA( viewPosition, 2.0f * VGUI_SCREEN_MODE_RADIUS, lookDir, lookEnd );

	Ray_t lookRay;
	lookRay.Init( viewPosition, lookEnd );

	// Look for vgui screens that are close to the player
	CVGuiScreenEnumerator localScreens;
	partition->EnumerateElementsInSphere( PARTITION_CLIENT_NON_STATIC_EDICTS, viewPosition, VGUI_SCREEN_MODE_RADIUS, false, &localScreens );

	Vector vecOut, vecViewDelta;

	float flBestDist = 2.0f;
	C_VGuiScreen *pBestScreen = NULL;
	for (int i = localScreens.GetScreenCount(); --i >= 0; )
	{
		C_VGuiScreen *pScreen = localScreens.GetVGuiScreen(i);

		if ( pScreen->IsAttachedToViewModel() )
			continue;

		// Don't bother with screens I'm behind...
		// Hax - don't cancel backfacing with viewmodel attached screens.
		// we can get prediction bugs that make us backfacing for one frame and
		// it resets the mouse position if we lose focus.
		if ( pScreen->IsBackfacing(viewPosition) )
			continue;

		// Don't bother with screens that are turned off
		if (!pScreen->IsActive())
			continue;

		// FIXME: Should this maybe go into a derived class of some sort?
		// Don't bother with screens on the wrong team
		if (!pScreen->IsVisibleToTeam(nTeam))
			continue;

		if ( !pScreen->AcceptsInput() )
			continue;

		if ( pScreen->IsInputOnlyToOwner() && pScreen->GetPlayerOwner() != pLocalPlayer )
			continue;

		// Test perpendicular distance from the screen...
		pScreen->GetVectors( NULL, NULL, &vecOut );
		VectorSubtract( viewPosition, pScreen->GetAbsOrigin(), vecViewDelta );
		float flPerpDist = DotProduct(vecViewDelta, vecOut);
		if ( (flPerpDist < 0) || (flPerpDist > VGUI_SCREEN_MODE_RADIUS) )
			continue;

		// Perform a raycast to see where in barycentric coordinates the ray hits
		// the viewscreen; if it doesn't hit it, you're not in the mode
		float u, v, t;
		if (!pScreen->IntersectWithRay( lookRay, &u, &v, &t ))
			continue;

		// Barycentric test
		if ((u < 0) || (v < 0) || (u > 1) || (v > 1))
			continue;

		if ( t < flBestDist )
		{
			flBestDist = t;
			pBestScreen = pScreen;
		}
	}
	
	return pBestScreen;
}
示例#15
0
void SP_trigger_fog (edict_t *self)
{
	fog_t *fog;

	if( !allow_fog->value )
	{
		G_FreeEdict(self);
		return;
	}
	if(deathmatch->value || coop->value)
	{
		G_FreeEdict(self);
		return;
	}

	self->class_id = ENTITY_TRIGGER_FOG;

	if(!level.fogs) level.fogs = 1;   // 1st fog reserved for console commands

	if(level.fogs >= MAX_FOGS)
	{
		gi.dprintf("Maximum number of fogs exceeded!\n");
		G_FreeEdict(self);
		return;
	}

	self->fog_index = level.fogs+1;
	fog = &gfogs[level.fogs];
	fog->Trigger = true;
	fog->Model   = self->fog_model;
	if(fog->Model < 0 || fog->Model > 2) fog->Model = 0;
	fog->GL_Model = GLModels[fog->Model];
	VectorCopy(self->fog_color,fog->Color);
	if(self->spawnflags & FOG_TURNOFF)
	{
		fog->Near    = 4999;
		fog->Far     = 5000;
		fog->Density = 0;
		fog->Density1 = 0;
		fog->Density2 = 0;
	}
	else
	{
		fog->Near    = self->fog_near;
		fog->Far     = self->fog_far;
		fog->Density = self->fog_density;
		fog->Density1 = self->fog_density;
		if(self->density == 0.)
			self->density = self->fog_density;
		else if(self->density < 0.)
			self->density = 0.;
		fog->Density2= self->density;
	}
	if(!(self->spawnflags & FOG_STARTOFF))
		self->spawnflags |= FOG_ON;

	AngleVectors(self->s.angles,fog->Dir,0,0);
	VectorClear(self->s.angles);
	fog->ent     = self;
	level.fogs++;
	level.trigger_fogs++;
	self->movetype = MOVETYPE_NONE;
	self->svflags |= SVF_NOCLIENT;
	self->solid = SOLID_NOT;
	gi.setmodel (self, self->model);
	gi.linkentity(self);
}
示例#16
0
/**
 * @brief Resolves ambient light, brightness, and contrast levels from Worldspawn.
 */
static void R_ResolveBspLightParameters(void) {
	const char *c;
	vec3_t tmp;

	// resolve ambient light
	if ((c = Cm_WorldspawnValue("ambient"))) {
		vec_t *f = r_bsp_light_state.ambient;
		sscanf(c, "%f %f %f", &f[0], &f[1], &f[2]);

		VectorScale(f, r_modulate->value, f);

		Com_Debug(DEBUG_RENDERER, "Resolved ambient: %s\n", vtos(f));
	} else {
		VectorSet(r_bsp_light_state.ambient, 0.15, 0.15, 0.15);
	}

	// resolve sun light
	if ((c = Cm_WorldspawnValue("sun_light"))) {
		r_bsp_light_state.sun.diffuse = atof(c) * BSP_LIGHT_SUN_SCALE;

		Com_Debug(DEBUG_RENDERER, "Resolved sun_light: %1.2f\n", r_bsp_light_state.sun.diffuse);
	} else {
		r_bsp_light_state.sun.diffuse = 0.0;
	}

	// resolve sun angles and direction
	if ((c = Cm_WorldspawnValue("sun_angles"))) {
		VectorClear(tmp);
		sscanf(c, "%f %f", &tmp[0], &tmp[1]);

		Com_Debug(DEBUG_RENDERER, "Resolved sun_angles: %s\n", vtos(tmp));
		AngleVectors(tmp, r_bsp_light_state.sun.dir, NULL, NULL);
	} else {
		VectorCopy(vec3_down, r_bsp_light_state.sun.dir);
	}

	// resolve sun color
	if ((c = Cm_WorldspawnValue("sun_color"))) {
		vec_t *f = r_bsp_light_state.sun.color;
		sscanf(c, "%f %f %f", &f[0], &f[1], &f[2]);

		Com_Debug(DEBUG_RENDERER, "Resolved sun_color: %s\n", vtos(f));
	} else {
		VectorSet(r_bsp_light_state.sun.color, 1.0, 1.0, 1.0);
	}

	// resolve brightness
	if ((c = Cm_WorldspawnValue("brightness"))) {
		r_bsp_light_state.brightness = atof(c);
	} else {
		r_bsp_light_state.brightness = 1.0;
	}

	// resolve saturation
	if ((c = Cm_WorldspawnValue("saturation"))) {
		r_bsp_light_state.saturation = atof(c);
	} else {
		r_bsp_light_state.saturation = 1.0;
	}

	// resolve contrast
	if ((c = Cm_WorldspawnValue("contrast"))) {
		r_bsp_light_state.contrast = atof(c);
	} else {
		r_bsp_light_state.contrast = 1.0;
	}

	Com_Debug(DEBUG_RENDERER, "Resolved brightness: %1.2f\n", r_bsp_light_state.brightness);
	Com_Debug(DEBUG_RENDERER, "Resolved saturation: %1.2f\n", r_bsp_light_state.saturation);
	Com_Debug(DEBUG_RENDERER, "Resolved contrast: %1.2f\n", r_bsp_light_state.contrast);

	const vec_t brt = r_bsp_light_state.brightness;
	const vec_t sat = r_bsp_light_state.saturation;
	const vec_t con = r_bsp_light_state.contrast;

	// apply brightness, saturation and contrast to the colors
	ColorFilter(r_bsp_light_state.ambient, r_bsp_light_state.ambient, brt, sat, con);
	Com_Debug(DEBUG_RENDERER, "Scaled ambient: %s\n", vtos(r_bsp_light_state.ambient));

	ColorFilter(r_bsp_light_state.sun.color, r_bsp_light_state.sun.color, brt, sat, con);
	Com_Debug(DEBUG_RENDERER, "Scaled sun color: %s\n", vtos(r_bsp_light_state.sun.color));
}
示例#17
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CPropAPC::Event_Killed( const CTakeDamageInfo &info )
{
	m_OnDeath.FireOutput( info.GetAttacker(), this );

	Vector vecAbsMins, vecAbsMaxs;
	CollisionProp()->WorldSpaceAABB( &vecAbsMins, &vecAbsMaxs );

	Vector vecNormalizedMins, vecNormalizedMaxs;
	CollisionProp()->WorldToNormalizedSpace( vecAbsMins, &vecNormalizedMins );
	CollisionProp()->WorldToNormalizedSpace( vecAbsMaxs, &vecNormalizedMaxs );

	Vector vecAbsPoint;
	CPASFilter filter( GetAbsOrigin() );
	for (int i = 0; i < 5; i++)
	{
		CollisionProp()->RandomPointInBounds( vecNormalizedMins, vecNormalizedMaxs, &vecAbsPoint );
		te->Explosion( filter, random->RandomFloat( 0.0, 1.0 ),	&vecAbsPoint, 
			g_sModelIndexFireball, random->RandomInt( 4, 10 ), 
			random->RandomInt( 8, 15 ), 
			( i < 2 ) ? TE_EXPLFLAG_NODLIGHTS : TE_EXPLFLAG_NOPARTICLES | TE_EXPLFLAG_NOFIREBALLSMOKE | TE_EXPLFLAG_NODLIGHTS,
			100, 0 );
	}

	// TODO: make the gibs spawn in sync with the delayed explosions
	int nGibs = random->RandomInt( 1, 4 );
	for ( int i = 0; i < nGibs; i++)
	{
		// Throw a flaming, smoking chunk.
		CGib *pChunk = CREATE_ENTITY( CGib, "gib" );
		pChunk->Spawn( "models/gibs/hgibs.mdl" );
		pChunk->SetBloodColor( DONT_BLEED );

		QAngle vecSpawnAngles;
		vecSpawnAngles.Random( -90, 90 );
		pChunk->SetAbsOrigin( vecAbsPoint );
		pChunk->SetAbsAngles( vecSpawnAngles );

		int nGib = random->RandomInt( 0, APC_MAX_CHUNKS - 1 );
		pChunk->Spawn( s_pChunkModelName[nGib] );
		pChunk->SetOwnerEntity( this );
		pChunk->m_lifeTime = random->RandomFloat( 6.0f, 8.0f );
		pChunk->SetCollisionGroup( COLLISION_GROUP_DEBRIS );
		IPhysicsObject *pPhysicsObject = pChunk->VPhysicsInitNormal( SOLID_VPHYSICS, pChunk->GetSolidFlags(), false );
		
		// Set the velocity
		if ( pPhysicsObject )
		{
			pPhysicsObject->EnableMotion( true );
			Vector vecVelocity;

			QAngle angles;
			angles.x = random->RandomFloat( -20, 20 );
			angles.y = random->RandomFloat( 0, 360 );
			angles.z = 0.0f;
			AngleVectors( angles, &vecVelocity );
			
			vecVelocity *= random->RandomFloat( 300, 900 );
			vecVelocity += GetAbsVelocity();

			AngularImpulse angImpulse;
			angImpulse = RandomAngularImpulse( -180, 180 );

			pChunk->SetAbsVelocity( vecVelocity );
			pPhysicsObject->SetVelocity(&vecVelocity, &angImpulse );
		}

		CEntityFlame *pFlame = CEntityFlame::Create( pChunk, false );
		if ( pFlame != NULL )
		{
			pFlame->SetLifetime( pChunk->m_lifeTime );
		}
	}

	UTIL_ScreenShake( vecAbsPoint, 25.0, 150.0, 1.0, 750.0f, SHAKE_START );

	if( hl2_episodic.GetBool() )
	{
		// EP1 perf hit
		Ignite( 6, false );
	}
	else
	{
		Ignite( 60, false );
	}

	m_lifeState = LIFE_DYING;

	// Spawn a lesser amount if the player is close
	m_iRocketSalvoLeft = DEATH_VOLLEY_ROCKET_COUNT;
	m_flRocketTime = gpGlobals->curtime;
}
示例#18
0
void EV_FireSG552( event_args_t *args )
{
	int idx;
	vec3_t origin;
	vec3_t angles;
	vec3_t velocity;

	vec3_t ShellVelocity;
	vec3_t ShellOrigin;
	int shell;
	vec3_t vecSrc, vecAiming;
	vec3_t up, right, forward;

	idx = args->entindex;
	VectorCopy( args->origin, origin );
	angles.x = (long double)args->iparam1 / 100 + args->angles[0];
	angles.y = (long double)args->iparam2 / 100 + args->angles[1];
	angles.z = args->angles[2];
	
	VectorCopy( args->velocity, velocity );

	AngleVectors( angles, forward, right, up );

	if ( EV_IsLocal( idx ) )
	{
		++g_iShotsFired;
		EV_MuzzleFlash();
		gEngfuncs.pEventAPI->EV_WeaponAnimation(gEngfuncs.pfnRandomLong(SG552_SHOOT1, SG552_SHOOT3), 2);
		if( !cl_righthand->value )
		{
			EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20.0, -8.0, -10.0, 0);
		}
		else
		{
			EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20.0, -8.0, 10.0, 0);
		}
	}
	else
	{
		EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20.0, -12.0, 4.0, 0);
	}

	shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/rshell.mdl");
	EV_EjectBrass(ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL);
	gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON,
		gEngfuncs.pfnRandomLong( 0, 1 ) ? "weapons/sg552-1.wav" : "weapons/sg552-2.wav",
		1, ATTN_NORM, 0,
		94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );


	EV_GetGunPosition( args, vecSrc, origin );
	VectorCopy( forward, vecAiming );
	Vector vSpread;
	int tracerCount;
	vSpread.x = args->fparam1;
	vSpread.y = args->fparam2;
	EV_HLDM_FireBullets( idx,
		forward, right,	up,
		1, vecSrc, vecAiming,
		vSpread, 8192.0, BULLET_PLAYER_556MM, 0, &tracerCount,
		2 );
}
示例#19
0
/*
================
R_DrawSprite
================
*/
void R_DrawSprite (void)
{
	int				i;
	msprite_t		*psprite;
	vec3_t			tvec;
	float			dot, angle, sr, cr;

	psprite = currententity->model->cache.data;

	r_spritedesc.pspriteframe = R_GetSpriteframe (psprite);

	sprite_width = r_spritedesc.pspriteframe->width;
	sprite_height = r_spritedesc.pspriteframe->height;

// TODO: make this caller-selectable
	if (psprite->type == SPR_FACING_UPRIGHT)
	{
	// generate the sprite's axes, with vup straight up in worldspace, and
	// r_spritedesc.vright perpendicular to modelorg.
	// This will not work if the view direction is very close to straight up or
	// down, because the cross product will be between two nearly parallel
	// vectors and starts to approach an undefined state, so we don't draw if
	// the two vectors are less than 1 degree apart
		tvec[0] = -modelorg[0];
		tvec[1] = -modelorg[1];
		tvec[2] = -modelorg[2];
		VectorNormalize (tvec);
		dot = tvec[2];	// same as DotProduct (tvec, r_spritedesc.vup) because
						//  r_spritedesc.vup is 0, 0, 1
		if ((dot > 0.999848) || (dot < -0.999848))	// cos(1 degree) = 0.999848
			return;
		r_spritedesc.vup[0] = 0;
		r_spritedesc.vup[1] = 0;
		r_spritedesc.vup[2] = 1;
		r_spritedesc.vright[0] = tvec[1];
								// CrossProduct(r_spritedesc.vup, -modelorg,
		r_spritedesc.vright[1] = -tvec[0];
								//              r_spritedesc.vright)
		r_spritedesc.vright[2] = 0;
		VectorNormalize (r_spritedesc.vright);
		r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
		r_spritedesc.vpn[1] = r_spritedesc.vright[0];
		r_spritedesc.vpn[2] = 0;
					// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
					//  r_spritedesc.vpn)
	}
	else if (psprite->type == SPR_VP_PARALLEL)
	{
	// generate the sprite's axes, completely parallel to the viewplane. There
	// are no problem situations, because the sprite is always in the same
	// position relative to the viewer
		for (i=0 ; i<3 ; i++)
		{
			r_spritedesc.vup[i] = vup[i];
			r_spritedesc.vright[i] = vright[i];
			r_spritedesc.vpn[i] = vpn[i];
		}
	}
	else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT)
	{
	// generate the sprite's axes, with vup straight up in worldspace, and
	// r_spritedesc.vright parallel to the viewplane.
	// This will not work if the view direction is very close to straight up or
	// down, because the cross product will be between two nearly parallel
	// vectors and starts to approach an undefined state, so we don't draw if
	// the two vectors are less than 1 degree apart
		dot = vpn[2];	// same as DotProduct (vpn, r_spritedesc.vup) because
						//  r_spritedesc.vup is 0, 0, 1
		if ((dot > 0.999848) || (dot < -0.999848))	// cos(1 degree) = 0.999848
			return;
		r_spritedesc.vup[0] = 0;
		r_spritedesc.vup[1] = 0;
		r_spritedesc.vup[2] = 1;
		r_spritedesc.vright[0] = vpn[1];
										// CrossProduct (r_spritedesc.vup, vpn,
		r_spritedesc.vright[1] = -vpn[0];	//  r_spritedesc.vright)
		r_spritedesc.vright[2] = 0;
		VectorNormalize (r_spritedesc.vright);
		r_spritedesc.vpn[0] = -r_spritedesc.vright[1];
		r_spritedesc.vpn[1] = r_spritedesc.vright[0];
		r_spritedesc.vpn[2] = 0;
					// CrossProduct (r_spritedesc.vright, r_spritedesc.vup,
					//  r_spritedesc.vpn)
	}
	else if (psprite->type == SPR_ORIENTED)
	{
	// generate the sprite's axes, according to the sprite's world orientation
		AngleVectors (currententity->angles, r_spritedesc.vpn,
					  r_spritedesc.vright, r_spritedesc.vup);
	}
	else if (psprite->type == SPR_VP_PARALLEL_ORIENTED)
	{
	// generate the sprite's axes, parallel to the viewplane, but rotated in
	// that plane around the center according to the sprite entity's roll
	// angle. So vpn stays the same, but vright and vup rotate
		angle = currententity->angles[ROLL] * (M_PI*2 / 360);
		sr = sin(angle);
		cr = cos(angle);

		for (i=0 ; i<3 ; i++)
		{
			r_spritedesc.vpn[i] = vpn[i];
			r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr;
			r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr;
		}
	}
	else
	{
		Sys_Error ("R_DrawSprite: Bad sprite type %d", psprite->type);
	}

	R_RotateSprite (psprite->beamlength);

	R_SetupAndDrawSprite ();
}
示例#20
0
文件: g_missile.c 项目: dmead/jkaq3
void G_MissileImpact( gentity_t *ent, trace_t *trace ) {
	gentity_t		*other;
	qboolean		hitClient = qfalse;
	qboolean		isKnockedSaber = qfalse;

	other = &g_entities[trace->entityNum];

	// check for bounce
	if ( !other->takedamage &&
		(ent->bounceCount > 0 || ent->bounceCount == -5) &&
		( ent->flags & ( FL_BOUNCE | FL_BOUNCE_HALF ) ) ) {
		G_BounceMissile( ent, trace );
		G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
		return;
	}
	else if (ent->neverFree && ent->s.weapon == WP_SABER && (ent->flags & FL_BOUNCE_HALF))
	{ //this is a knocked-away saber
		if (ent->bounceCount > 0 || ent->bounceCount == -5)
		{
			G_BounceMissile( ent, trace );
			G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
			return;
		}

		isKnockedSaber = qtrue;
	}
	
	// I would glom onto the FL_BOUNCE code section above, but don't feel like risking breaking something else
	if ( (!other->takedamage && (ent->bounceCount > 0 || ent->bounceCount == -5) && ( ent->flags&(FL_BOUNCE_SHRAPNEL) ) ) || ((trace->surfaceFlags&SURF_FORCEFIELD)&&!ent->splashDamage&&!ent->splashRadius&&(ent->bounceCount > 0 || ent->bounceCount == -5)) ) 
	{
		G_BounceMissile( ent, trace );

		if ( ent->bounceCount < 1 )
		{
			ent->flags &= ~FL_BOUNCE_SHRAPNEL;
		}
		return;
	}

	/*
	if ( !other->takedamage && ent->s.weapon == WP_THERMAL && !ent->alt_fire )
	{//rolling thermal det - FIXME: make this an eFlag like bounce & stick!!!
		//G_BounceRollMissile( ent, trace );
		if ( ent->owner && ent->owner->s.number == 0 ) 
		{
			G_MissileAddAlerts( ent );
		}
		//gi.linkentity( ent );
		return;
	}
	*/

	if ((other->r.contents & CONTENTS_LIGHTSABER) && !isKnockedSaber)
	{ //hit this person's saber, so..
		gentity_t *otherOwner = &g_entities[other->r.ownerNum];

		if (otherOwner->takedamage && otherOwner->client && otherOwner->client->ps.duelInProgress &&
			otherOwner->client->ps.duelIndex != ent->r.ownerNum)
		{
			goto killProj;
		}
	}
	else if (!isKnockedSaber)
	{
		if (other->takedamage && other->client && other->client->ps.duelInProgress &&
			other->client->ps.duelIndex != ent->r.ownerNum)
		{
			goto killProj;
		}
	}

	if (other->flags & FL_DMG_BY_HEAVY_WEAP_ONLY)
	{
		if (ent->methodOfDeath != MOD_REPEATER_ALT &&
			ent->methodOfDeath != MOD_ROCKET &&
			ent->methodOfDeath != MOD_FLECHETTE_ALT_SPLASH &&
			ent->methodOfDeath != MOD_ROCKET_HOMING &&
			ent->methodOfDeath != MOD_THERMAL &&
			ent->methodOfDeath != MOD_THERMAL_SPLASH &&
			ent->methodOfDeath != MOD_TRIP_MINE_SPLASH &&
			ent->methodOfDeath != MOD_TIMED_MINE_SPLASH &&
			ent->methodOfDeath != MOD_DET_PACK_SPLASH &&
			ent->methodOfDeath != MOD_VEHICLE &&
			ent->methodOfDeath != MOD_CONC &&
			ent->methodOfDeath != MOD_CONC_ALT &&
			ent->methodOfDeath != MOD_SABER &&
			ent->methodOfDeath != MOD_TURBLAST)
		{
			vec3_t fwd;

			if (trace)
			{
				VectorCopy(trace->plane.normal, fwd);
			}
			else
			{ //oh well
				AngleVectors(other->r.currentAngles, fwd, NULL, NULL);
			}

			G_DeflectMissile(other, ent, fwd);
			G_MissileBounceEffect(ent, ent->r.currentOrigin, fwd);
			return;
		}
	}

	if ((other->flags & FL_SHIELDED) &&
		ent->s.weapon != WP_ROCKET_LAUNCHER &&
		ent->s.weapon != WP_THERMAL &&
		ent->s.weapon != WP_TRIP_MINE &&
		ent->s.weapon != WP_DET_PACK &&
		ent->s.weapon != WP_DEMP2 &&
		ent->s.weapon != WP_EMPLACED_GUN &&
		ent->methodOfDeath != MOD_REPEATER_ALT &&
		ent->methodOfDeath != MOD_FLECHETTE_ALT_SPLASH && 
		ent->methodOfDeath != MOD_TURBLAST &&
		ent->methodOfDeath != MOD_VEHICLE &&
		ent->methodOfDeath != MOD_CONC &&
		ent->methodOfDeath != MOD_CONC_ALT &&
		!(ent->dflags&DAMAGE_HEAVY_WEAP_CLASS) )
	{
		vec3_t fwd;

		if (other->client)
		{
			AngleVectors(other->client->ps.viewangles, fwd, NULL, NULL);
		}
		else
		{
			AngleVectors(other->r.currentAngles, fwd, NULL, NULL);
		}

		G_DeflectMissile(other, ent, fwd);
		G_MissileBounceEffect(ent, ent->r.currentOrigin, fwd);
		return;
	}
		
	if (other->takedamage && other->client &&
		ent->s.weapon != WP_ROCKET_LAUNCHER &&
		ent->s.weapon != WP_THERMAL &&
		ent->s.weapon != WP_TRIP_MINE &&
		ent->s.weapon != WP_DET_PACK &&
		ent->s.weapon != WP_DEMP2 &&
		ent->methodOfDeath != MOD_REPEATER_ALT &&
		ent->methodOfDeath != MOD_FLECHETTE_ALT_SPLASH &&
		ent->methodOfDeath != MOD_CONC &&
		ent->methodOfDeath != MOD_CONC_ALT &&
		other->client->ps.saberBlockTime < level.time &&
		!isKnockedSaber &&
		WP_SaberCanBlock(other, ent->r.currentOrigin, 0, 0, qtrue, 0))
	{ //only block one projectile per 200ms (to prevent giant swarms of projectiles being blocked)
		vec3_t fwd;
		gentity_t *te;
		int otherDefLevel = other->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE];

		te = G_TempEntity( ent->r.currentOrigin, EV_SABER_BLOCK );
		VectorCopy(ent->r.currentOrigin, te->s.origin);
		VectorCopy(trace->plane.normal, te->s.angles);
		te->s.eventParm = 0;
		te->s.weapon = 0;//saberNum
		te->s.legsAnim = 0;//bladeNum

		/*if (other->client->ps.velocity[2] > 0 ||
			other->client->pers.cmd.forwardmove ||
			other->client->pers.cmd.rightmove)
			*/
		if (other->client->ps.velocity[2] > 0 ||
			other->client->pers.cmd.forwardmove < 0) //now we only do it if jumping or running backward. Should be able to full-on charge.
		{
			otherDefLevel -= 1;
			if (otherDefLevel < 0)
			{
				otherDefLevel = 0;
			}
		}

		AngleVectors(other->client->ps.viewangles, fwd, NULL, NULL);
		if (otherDefLevel == FORCE_LEVEL_1)
		{
			//if def is only level 1, instead of deflecting the shot it should just die here
		}
		else if (otherDefLevel == FORCE_LEVEL_2)
		{
			G_DeflectMissile(other, ent, fwd);
		}
		else
		{
			G_ReflectMissile(other, ent, fwd);
		}
		other->client->ps.saberBlockTime = level.time + (350 - (otherDefLevel*100)); //200;

		//For jedi AI
		other->client->ps.saberEventFlags |= SEF_DEFLECTED;

		if (otherDefLevel == FORCE_LEVEL_3)
		{
			other->client->ps.saberBlockTime = 0; //^_^
		}

		if (otherDefLevel == FORCE_LEVEL_1)
		{
			goto killProj;
		}
		return;
	}
	else if ((other->r.contents & CONTENTS_LIGHTSABER) && !isKnockedSaber)
	{ //hit this person's saber, so..
		gentity_t *otherOwner = &g_entities[other->r.ownerNum];

		if (otherOwner->takedamage && otherOwner->client &&
			ent->s.weapon != WP_ROCKET_LAUNCHER &&
			ent->s.weapon != WP_THERMAL &&
			ent->s.weapon != WP_TRIP_MINE &&
			ent->s.weapon != WP_DET_PACK &&
			ent->s.weapon != WP_DEMP2 &&
			ent->methodOfDeath != MOD_REPEATER_ALT &&
			ent->methodOfDeath != MOD_FLECHETTE_ALT_SPLASH &&
			ent->methodOfDeath != MOD_CONC &&
			ent->methodOfDeath != MOD_CONC_ALT /*&&
			otherOwner->client->ps.saberBlockTime < level.time*/)
		{ //for now still deflect even if saberBlockTime >= level.time because it hit the actual saber
			vec3_t fwd;
			gentity_t *te;
			int otherDefLevel = otherOwner->client->ps.fd.forcePowerLevel[FP_SABER_DEFENSE];

			//in this case, deflect it even if we can't actually block it because it hit our saber
			//WP_SaberCanBlock(otherOwner, ent->r.currentOrigin, 0, 0, qtrue, 0);
			if (otherOwner->client && otherOwner->client->ps.weaponTime <= 0)
			{
				WP_SaberBlockNonRandom(otherOwner, ent->r.currentOrigin, qtrue);
			}

			te = G_TempEntity( ent->r.currentOrigin, EV_SABER_BLOCK );
			VectorCopy(ent->r.currentOrigin, te->s.origin);
			VectorCopy(trace->plane.normal, te->s.angles);
			te->s.eventParm = 0;
			te->s.weapon = 0;//saberNum
			te->s.legsAnim = 0;//bladeNum

			/*if (otherOwner->client->ps.velocity[2] > 0 ||
				otherOwner->client->pers.cmd.forwardmove ||
				otherOwner->client->pers.cmd.rightmove)*/
			if (otherOwner->client->ps.velocity[2] > 0 ||
				otherOwner->client->pers.cmd.forwardmove < 0) //now we only do it if jumping or running backward. Should be able to full-on charge.
			{
				otherDefLevel -= 1;
				if (otherDefLevel < 0)
				{
					otherDefLevel = 0;
				}
			}

			AngleVectors(otherOwner->client->ps.viewangles, fwd, NULL, NULL);

			if (otherDefLevel == FORCE_LEVEL_1)
			{
				//if def is only level 1, instead of deflecting the shot it should just die here
			}
			else if (otherDefLevel == FORCE_LEVEL_2)
			{
				G_DeflectMissile(otherOwner, ent, fwd);
			}
			else
			{
				G_ReflectMissile(otherOwner, ent, fwd);
			}
			otherOwner->client->ps.saberBlockTime = level.time + (350 - (otherDefLevel*100));//200;

			//For jedi AI
			otherOwner->client->ps.saberEventFlags |= SEF_DEFLECTED;

			if (otherDefLevel == FORCE_LEVEL_3)
			{
				otherOwner->client->ps.saberBlockTime = 0; //^_^
			}

			if (otherDefLevel == FORCE_LEVEL_1)
			{
				goto killProj;
			}
			return;
		}
	}

	// check for sticking
	if ( !other->takedamage && ( ent->s.eFlags & EF_MISSILE_STICK ) ) 
	{
		laserTrapStick( ent, trace->endpos, trace->plane.normal );
		G_AddEvent( ent, EV_MISSILE_STICK, 0 );
		return;
	}

	// impact damage
	if (other->takedamage && !isKnockedSaber) {
		// FIXME: wrong damage direction?
		if ( ent->damage ) {
			vec3_t	velocity;
			qboolean didDmg = qfalse;

			if( LogAccuracyHit( other, &g_entities[ent->r.ownerNum] ) ) {
				g_entities[ent->r.ownerNum].client->accuracy_hits++;
				hitClient = qtrue;
			}
			BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity );
			if ( VectorLength( velocity ) == 0 ) {
				velocity[2] = 1;	// stepped on a grenade
			}

			if (ent->s.weapon == WP_BOWCASTER || ent->s.weapon == WP_FLECHETTE ||
				ent->s.weapon == WP_ROCKET_LAUNCHER)
			{
				if (ent->s.weapon == WP_FLECHETTE && (ent->s.eFlags & EF_ALT_FIRING))
				{
					ent->think(ent);
				}
				else
				{
					G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity,
						/*ent->s.origin*/ent->r.currentOrigin, ent->damage, 
						DAMAGE_HALF_ABSORB, ent->methodOfDeath);
					didDmg = qtrue;
				}
			}
			else
			{
				G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity,
					/*ent->s.origin*/ent->r.currentOrigin, ent->damage, 
					0, ent->methodOfDeath);
				didDmg = qtrue;
			}

			if (didDmg && other && other->client)
			{ //What I'm wondering is why this isn't in the NPC pain funcs. But this is what SP does, so whatever.
				class_t	npc_class = other->client->NPC_class;

				// If we are a robot and we aren't currently doing the full body electricity...
				if ( npc_class == CLASS_SEEKER || npc_class == CLASS_PROBE || npc_class == CLASS_MOUSE ||
					   npc_class == CLASS_GONK || npc_class == CLASS_R2D2 || npc_class == CLASS_R5D2 || npc_class == CLASS_REMOTE ||
					   npc_class == CLASS_MARK1 || npc_class == CLASS_MARK2 || //npc_class == CLASS_PROTOCOL ||//no protocol, looks odd
					   npc_class == CLASS_INTERROGATOR || npc_class == CLASS_ATST || npc_class == CLASS_SENTRY )
				{
					// special droid only behaviors
					if ( other->client->ps.electrifyTime < level.time + 100 )
					{
						// ... do the effect for a split second for some more feedback
						other->client->ps.electrifyTime = level.time + 450;
					}
					//FIXME: throw some sparks off droids,too
				}
			}
		}

		if ( ent->s.weapon == WP_DEMP2 )
		{//a hit with demp2 decloaks people, disables ships
			if ( other && other->client && other->client->NPC_class == CLASS_VEHICLE )
			{//hit a vehicle
				if ( other->m_pVehicle //valid vehicle ent
					&& other->m_pVehicle->m_pVehicleInfo//valid stats
					&& (other->m_pVehicle->m_pVehicleInfo->type == VH_SPEEDER//always affect speeders
						||(other->m_pVehicle->m_pVehicleInfo->type == VH_FIGHTER && ent->classname && Q_stricmp("vehicle_proj", ent->classname ) == 0) )//only vehicle ion weapons affect a fighter in this manner
					&& !FighterIsLanded( other->m_pVehicle , &other->client->ps )//not landed
					&& !(other->spawnflags&2) )//and not suspended
				{//vehicles hit by "ion cannons" lose control
					if ( other->client->ps.electrifyTime > level.time )
					{//add onto it
						//FIXME: extern the length of the "out of control" time?
						other->client->ps.electrifyTime += Q_irand(200,500);
						if ( other->client->ps.electrifyTime > level.time + 4000 )
						{//cap it
							other->client->ps.electrifyTime = level.time + 4000;
						}
					}
					else
					{//start it
						//FIXME: extern the length of the "out of control" time?
						other->client->ps.electrifyTime = level.time + Q_irand(200,500);
					}
				}
			}
			else if ( other && other->client && other->client->ps.powerups[PW_CLOAKED] )
			{
				Jedi_Decloak( other );
				if ( ent->methodOfDeath == MOD_DEMP2_ALT )
				{//direct hit with alt disables cloak forever
					//permanently disable the saboteur's cloak
					other->client->cloakToggleTime = Q3_INFINITE;
				}
				else
				{//temp disable
					other->client->cloakToggleTime = level.time + Q_irand( 3000, 10000 );
				}
			}
		}
	}
killProj:
	// is it cheaper in bandwidth to just remove this ent and create a new
	// one, rather than changing the missile into the explosion?

	if ( other->takedamage && other->client && !isKnockedSaber ) {
		G_AddEvent( ent, EV_MISSILE_HIT, DirToByte( trace->plane.normal ) );
		ent->s.otherEntityNum = other->s.number;
	} else if( trace->surfaceFlags & SURF_METALSTEPS ) {
		G_AddEvent( ent, EV_MISSILE_MISS_METAL, DirToByte( trace->plane.normal ) );
	} else if (ent->s.weapon != G2_MODEL_PART && !isKnockedSaber) {
		G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( trace->plane.normal ) );
	}

	if (!isKnockedSaber)
	{
		ent->freeAfterEvent = qtrue;

		// change over to a normal entity right at the point of impact
		ent->s.eType = ET_GENERAL;
	}

	SnapVectorTowards( trace->endpos, ent->s.pos.trBase );	// save net bandwidth

	G_SetOrigin( ent, trace->endpos );

	ent->takedamage = qfalse;
	// splash damage (doesn't apply to person directly hit)
	if ( ent->splashDamage ) {
		if( G_RadiusDamage( trace->endpos, ent->parent, ent->splashDamage, ent->splashRadius, 
			other, ent, ent->splashMethodOfDeath ) ) {
			if( !hitClient 
				&& g_entities[ent->r.ownerNum].client ) {
				g_entities[ent->r.ownerNum].client->accuracy_hits++;
			}
		}
	}

	if (ent->s.weapon == G2_MODEL_PART)
	{
		ent->freeAfterEvent = qfalse; //it will free itself
	}

	trap_LinkEntity( ent );
}
示例#21
0
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFastZombie::StartTask( const Task_t *pTask )
{
    switch( pTask->iTask )
    {
    case TASK_FASTZOMBIE_VERIFY_ATTACK:
        // Simply ensure that the zombie still has a valid melee attack
        if( HasCondition( COND_CAN_MELEE_ATTACK1 ) )
        {
            TaskComplete();
        }
        else
        {
            TaskFail("");
        }
        break;

    case TASK_FASTZOMBIE_JUMP_BACK:
    {
        SetActivity( ACT_IDLE );

        RemoveFlag( FL_ONGROUND );

        BeginAttackJump();

        Vector forward;
        AngleVectors( GetLocalAngles(), &forward );

        //
        // Take him off ground so engine doesn't instantly reset FL_ONGROUND.
        //
        UTIL_SetOrigin( this, GetLocalOrigin() + Vector( 0 , 0 , 1 ));

        ApplyAbsVelocityImpulse( forward * -200 + Vector( 0, 0, 200 ) );
    }
    break;

    case TASK_FASTZOMBIE_UNSTICK_JUMP:
    {
        RemoveFlag( FL_ONGROUND );

        // Call begin attack jump. A little bit later if we fail to pathfind, we check
        // this value to see if we just jumped. If so, we assume we've jumped
        // to someplace that's not pathing friendly, and so must jump again to get out.
        BeginAttackJump();

        //
        // Take him off ground so engine doesn't instantly reset FL_ONGROUND.
        //
        UTIL_SetOrigin( this, GetLocalOrigin() + Vector( 0 , 0 , 1 ));

        CBaseEntity *pEnemy = GetEnemy();
        Vector vecJumpDir;

        if ( GetActivity() == ACT_CLIMB_UP || GetActivity() == ACT_CLIMB_DOWN )
        {
            // Jump off the pipe backwards!
            Vector forward;

            GetVectors( &forward, NULL, NULL );

            ApplyAbsVelocityImpulse( forward * -200 );
        }
        else if( pEnemy )
        {
            vecJumpDir = pEnemy->GetLocalOrigin() - GetLocalOrigin();
            VectorNormalize( vecJumpDir );
            vecJumpDir.z = 0;

            ApplyAbsVelocityImpulse( vecJumpDir * 300 + Vector( 0, 0, 200 ) );
        }
        else
        {
            Msg("UNHANDLED CASE! Stuck Fast Zombie with no enemy!\n");
        }
    }
    break;

    case TASK_WAIT_FOR_MOVEMENT:
        // If we're waiting for movement, that means that pathfinding succeeded, and
        // we're about to be moving. So we aren't stuck. So clear this flag.
        m_fJustJumped = false;

        BaseClass::StartTask( pTask );
        break;

    case TASK_FACE_ENEMY:
    {
        // We don't use the base class implementation of this, because GetTurnActivity
        // stomps our landing scrabble animations (sjb)
        Vector flEnemyLKP = GetEnemyLKP();
        GetMotor()->SetIdealYawToTarget( flEnemyLKP );
    }
    break;

    case TASK_FASTZOMBIE_LAND_RECOVER:
    {
        // Set the ideal yaw
        Vector flEnemyLKP = GetEnemyLKP();
        GetMotor()->SetIdealYawToTarget( flEnemyLKP );

        // figure out which way to turn.
        float flDeltaYaw = GetMotor()->DeltaIdealYaw();

        if( flDeltaYaw < 0 )
        {
            SetIdealActivity( (Activity)ACT_FASTZOMBIE_LAND_RIGHT );
        }
        else
        {
            SetIdealActivity( (Activity)ACT_FASTZOMBIE_LAND_LEFT );
        }


        TaskComplete();
    }
    break;

    case TASK_RANGE_ATTACK1:

        // Make melee attacks impossible until we land!
        m_flNextMeleeAttack = gpGlobals->curtime + 60;

        SetTouch( LeapAttackTouch );
        break;

    case TASK_FASTZOMBIE_DO_ATTACK:
        SetActivity( (Activity)ACT_FASTZOMBIE_LEAP_SOAR );
        break;

    default:
        BaseClass::StartTask( pTask );
        break;
    }
}
void hyperspace_touch( gentity_t *self, gentity_t *other, trace_t *trace )
{
	gentity_t *ent;

	if (!other || !other->inuse || !other->client ||
		other->s.number < MAX_CLIENTS ||
		!other->m_pVehicle)
	{ //only let vehicles touch
		return;
	}

	if ( other->client->ps.hyperSpaceTime && level.time - other->client->ps.hyperSpaceTime < HYPERSPACE_TIME )
	{//already hyperspacing, just keep us moving
		if ( (other->client->ps.eFlags2&EF2_HYPERSPACE) )
		{//they've started the hyperspace but haven't been teleported yet
			float timeFrac = ((float)(level.time-other->client->ps.hyperSpaceTime))/HYPERSPACE_TIME;
			if ( timeFrac >= HYPERSPACE_TELEPORT_FRAC )
			{//half-way, now teleport them!
				vec3_t	diff, fwd, right, up, newOrg;
				float	fDiff, rDiff, uDiff;
				//take off the flag so we only do this once
				other->client->ps.eFlags2 &= ~EF2_HYPERSPACE;
				//Get the offset from the local position
				ent = G_Find (NULL, FOFS(targetname), self->target);
				if (!ent || !ent->inuse)
				{ //this is bad
					trap->Error(ERR_DROP, "trigger_hyperspace has invalid target '%s'\n", self->target);
					return;
				}
				VectorSubtract( other->client->ps.origin, ent->s.origin, diff );
				AngleVectors( ent->s.angles, fwd, right, up );
				fDiff = DotProduct( fwd, diff );
				rDiff = DotProduct( right, diff );
				uDiff = DotProduct( up, diff );
				//Now get the base position of the destination
				ent = G_Find (NULL, FOFS(targetname), self->target2);
				if (!ent || !ent->inuse)
				{ //this is bad
					trap->Error(ERR_DROP, "trigger_hyperspace has invalid target2 '%s'\n", self->target2);
					return;
				}
				VectorCopy( ent->s.origin, newOrg );
				//finally, add the offset into the new origin
				AngleVectors( ent->s.angles, fwd, right, up );
				VectorMA( newOrg, fDiff, fwd, newOrg );
				VectorMA( newOrg, rDiff, right, newOrg );
				VectorMA( newOrg, uDiff, up, newOrg );
				//trap->Print("hyperspace from %s to %s\n", vtos(other->client->ps.origin), vtos(newOrg) );
				//now put them in the offset position, facing the angles that position wants them to be facing
				TeleportPlayer( other, newOrg, ent->s.angles );
				if ( other->m_pVehicle && other->m_pVehicle->m_pPilot )
				{//teleport the pilot, too
					TeleportPlayer( (gentity_t*)other->m_pVehicle->m_pPilot, newOrg, ent->s.angles );
					//FIXME: and the passengers?
				}
				//make them face the new angle
				//other->client->ps.hyperSpaceIndex = ent->s.number;
				VectorCopy( ent->s.angles, other->client->ps.hyperSpaceAngles );
				//sound
				G_Sound( other, CHAN_LOCAL, G_SoundIndex( "sound/vehicles/common/hyperend.wav" ) );
			}
		}
		return;
	}
	else
	{
		ent = G_Find (NULL, FOFS(targetname), self->target);
		if (!ent || !ent->inuse)
		{ //this is bad
			trap->Error(ERR_DROP, "trigger_hyperspace has invalid target '%s'\n", self->target);
			return;
		}

		if (!other->client->ps.m_iVehicleNum || other->m_pVehicle->m_iRemovedSurfaces)
		{ //if a vehicle touches a boundary without a pilot in it or with parts missing, just blow the thing up
			G_Damage(other, other, other, NULL, other->client->ps.origin, 99999, DAMAGE_NO_PROTECTION, MOD_SUICIDE);
			return;
		}
		//other->client->ps.hyperSpaceIndex = ent->s.number;
		VectorCopy( ent->s.angles, other->client->ps.hyperSpaceAngles );
		other->client->ps.hyperSpaceTime = level.time;
	}
}
//-----------------------------------------------------------------------------
// Purpose: Catches the monster-specific messages that occur when tagged
//			animation frames are played.
// Input  : *pEvent - 
//-----------------------------------------------------------------------------
void CNPC_Headcrab::HandleAnimEvent( animevent_t *pEvent )
{
	switch ( pEvent->event )
	{
		case HC_AE_JUMPATTACK:
		{
			RemoveFlag( FL_ONGROUND );

			//
			// Take him off ground so engine doesn't instantly reset FL_ONGROUND.
			//
			UTIL_SetOrigin( this, GetAbsOrigin() + Vector( 0 , 0 , 1 ));

			Vector vecJumpDir;
			CBaseEntity *pEnemy = GetEnemy();
			if ( pEnemy )
			{
				Vector vecEnemyEyePos = pEnemy->EyePosition();

				float gravity = sv_gravity.GetFloat();
				if ( gravity <= 1 )
				{
					gravity = 1;
				}

				//
				// How fast does the headcrab need to travel to reach my enemy's eyes given gravity?
				//
				float height = ( vecEnemyEyePos.z - GetAbsOrigin().z );
				if ( height < 16 )
				{
					height = 16;
				}
				else if ( height > 120 )
				{
					height = 120;
				}
				float speed = sqrt( 2 * gravity * height );
				float time = speed / gravity;

				//
				// Scale the sideways velocity to get there at the right time
				//
				vecJumpDir = vecEnemyEyePos - GetAbsOrigin();
				vecJumpDir = vecJumpDir / time;

				//
				// Speed to offset gravity at the desired height.
				//
				vecJumpDir.z = speed;

				//
				// Don't jump too far/fast.
				//
				float distance = vecJumpDir.Length();
				if ( distance > 650 )
				{
					vecJumpDir = vecJumpDir * ( 650.0 / distance );
				}
			}
			else
			{
				//
				// Jump hop, don't care where.
				//
				Vector forward, up;
				AngleVectors( GetAbsAngles(), &forward, NULL, &up );
				vecJumpDir = Vector( forward.x, forward.y, up.z ) * 350;
			}

			int iSound = random->RandomInt( 0 , 1 );
			if ( iSound != 0 )
			{
				AttackSound();
			}

			SetAbsVelocity( vecJumpDir );
			m_flNextAttack = gpGlobals->curtime + 2;
			break;
		}

		default:
		{
			CAI_BaseNPC::HandleAnimEvent( pEvent );
			break;
		}
	}
}
void Touch_Multi( gentity_t *self, gentity_t *other, trace_t *trace ) 
{
	if( !other->client ) 
	{
		return;
	}

	if ( self->flags & FL_INACTIVE )
	{//set by target_deactivate
		return;
	}

#ifdef _PHASE1
	if (self->spawnflags & 32 && jkg_arearestrictions.integer)
	{
		return;	// eezstreet: Pande's orders
	}
#endif

	if( self->alliedTeam )
	{
		if ( other->client->sess.sessionTeam != self->alliedTeam )
		{
			return;
		}
	}

// moved to just above multi_trigger because up here it just checks if the trigger is not being touched
// we want it to check any conditions set on the trigger, if one of those isn't met, the trigger is considered to be "cleared"
//	if ( self->e_ThinkFunc == thinkF_trigger_cleared_fire )
//	{//We're waiting to fire our target2 first
//		self->nextthink = level.time + self->speed;
//		return;
//	}

	if ( self->spawnflags & 1 )
	{
		if ( other->s.eType == ET_NPC )
		{
			return;
		}
	}
	else
	{
		if ( self->spawnflags & 16 )
		{//NPCONLY
			if ( other->NPC == NULL )
			{
				return;
			}
		}

		if ( self->NPC_targetname && self->NPC_targetname[0] )
		{
			if ( other->script_targetname && other->script_targetname[0] )
			{
				if ( Q_stricmp( self->NPC_targetname, other->script_targetname ) != 0 )
				{//not the right guy to fire me off
					return;
				}
			}
			else
			{
				return;
			}
		}
	}

	if ( self->spawnflags & 2 )
	{//FACING
		vec3_t	forward;

		AngleVectors( other->client->ps.viewangles, forward, NULL, NULL );

		if ( DotProduct( self->movedir, forward ) < 0.5 )
		{//Not Within 45 degrees
			return;
		}
	}

	if ( self->spawnflags & 4 )
	{//USE_BUTTON
		if( !( other->client->pers.cmd.buttons & BUTTON_USE ) )
		{//not pressing use button
			return;
		}

		if ((other->client->ps.weaponTime > 0 && other->client->ps.torsoAnim != BOTH_BUTTON_HOLD && other->client->ps.torsoAnim != BOTH_CONSOLE1) || other->health < 1 ||
			(other->client->ps.pm_flags & PMF_FOLLOW) || other->client->sess.sessionTeam == TEAM_SPECTATOR ||
			other->client->ps.forceHandExtend != HANDEXTEND_NONE)
		{ //player has to be free of other things to use.
			return;
		}

		if (self->genericValue7)
		{ //we have to be holding the use key in this trigger for x milliseconds before firing
			if (!G_PointInBounds( other->client->ps.origin, self->r.absmin, self->r.absmax ))
			{
				return;
			}
			else if (other->client->isHacking != self->s.number && other->s.number < MAX_CLIENTS )
			{ //start the hack
				other->client->isHacking = self->s.number;
				VectorCopy(other->client->ps.viewangles, other->client->hackingAngles);
				other->client->ps.hackingTime = level.time + self->genericValue7;
				other->client->ps.hackingBaseTime = self->genericValue7;
				if (other->client->ps.hackingBaseTime > 60000)
				{ //don't allow a bit overflow
					other->client->ps.hackingTime = level.time + 60000;
					other->client->ps.hackingBaseTime = 60000;
				}
				return;
			}
			else if (other->client->ps.hackingTime < level.time)
			{ //finished with the hack, reset the hacking values and let it fall through
				other->client->isHacking = 0; //can't hack a client
				other->client->ps.hackingTime = 0;
			}
			else
			{ //hack in progress
				// UQ1: Added this code from below... It would never have gotten there before...
				if (other->client->ps.torsoAnim != BOTH_BUTTON_HOLD &&
					other->client->ps.torsoAnim != BOTH_CONSOLE1)
				{
					G_SetAnim( other, NULL, SETANIM_TORSO, BOTH_BUTTON_HOLD, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				}
				else
				{
					other->client->ps.torsoTimer = 500;
				}
				other->client->ps.weaponTime = other->client->ps.torsoTimer;
				// UQ1: End added...
				return;
			}
		}
	}

	if ( self->spawnflags & 8 )
	{//FIRE_BUTTON
		if( !( other->client->pers.cmd.buttons & BUTTON_ATTACK ) )
		{//not pressing fire button or altfire button
			return;
		}
	}

	if ( self->radius )
	{
		vec3_t	eyeSpot;

		//Only works if your head is in it, but we allow leaning out
		//NOTE: We don't use CalcEntitySpot SPOT_HEAD because we don't want this
		//to be reliant on the physical model the player uses.
		VectorCopy(other->client->ps.origin, eyeSpot);
		eyeSpot[2] += other->client->ps.viewheight;

		if ( G_PointInBounds( eyeSpot, self->r.absmin, self->r.absmax ) )
		{
			if( !( other->client->pers.cmd.buttons & BUTTON_ATTACK ) )
			{//not attacking, so hiding bonus
				/*
				//FIXME:  should really have sound events clear the hiddenDist
				other->client->hiddenDist = self->radius;
				//NOTE: movedir HAS to be normalized!
				if ( VectorLength( self->movedir ) )
				{//They can only be hidden from enemies looking in this direction
					VectorCopy( self->movedir, other->client->hiddenDir );
				}
				else
				{
					VectorClear( other->client->hiddenDir );
				}
				*/
				//Not using this, at least not yet.
			}
		}
	}

	if ( self->spawnflags & 4 )
	{//USE_BUTTON
		if (other->client->ps.torsoAnim != BOTH_BUTTON_HOLD &&
			other->client->ps.torsoAnim != BOTH_CONSOLE1)
		{
			G_SetAnim( other, NULL, SETANIM_TORSO, BOTH_BUTTON_HOLD, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
		}
		else
		{
			other->client->ps.torsoTimer = 500;
		}
		other->client->ps.weaponTime = other->client->ps.torsoTimer;
	}
	
	if ( self->think == trigger_cleared_fire )
	{//We're waiting to fire our target2 first
		self->nextthink = level.time + self->speed;
		return;
	}

	multi_trigger( self, other );
}
示例#25
0
文件: g_object.c 项目: Boothand/jk2mp
void pitch_roll_for_slope( gentity_t *forwhom, vec3_t pass_slope )
{
	vec3_t	slope;
	vec3_t	nvf, ovf, ovr, startspot, endspot, new_angles = { 0, 0, 0 };
	float	pitch, mod, dot;
	float	oldmins2;

	//if we don't have a slope, get one
	if( !pass_slope || VectorCompare( vec3_origin, pass_slope ) )
	{
		trace_t trace;

		VectorCopy( forwhom->r.currentOrigin, startspot );
		startspot[2] += forwhom->r.mins[2] + 4;
		VectorCopy( startspot, endspot );
		endspot[2] -= 300;
		trap_Trace( &trace, forwhom->r.currentOrigin, vec3_origin, vec3_origin, endspot, forwhom->s.number, MASK_SOLID );
//		if(trace_fraction>0.05&&forwhom.movetype==MOVETYPE_STEP)
//			forwhom.flags(-)FL_ONGROUND;

		if ( trace.fraction >= 1.0 )
			return;

		if( !( &trace.plane ) )
			return;

		if ( VectorCompare( vec3_origin, trace.plane.normal ) )
			return;

		VectorCopy( trace.plane.normal, slope );
	}
	else
	{
		VectorCopy( pass_slope, slope );
	}


	AngleVectors( forwhom->r.currentAngles, ovf, ovr, NULL );

	vectoangles( slope, new_angles );
	pitch = new_angles[PITCH] + 90;
	new_angles[ROLL] = new_angles[PITCH] = 0;

	AngleVectors( new_angles, nvf, NULL, NULL );

	mod = DotProduct( nvf, ovr );

	if ( mod<0 )
		mod = -1;
	else
		mod = 1;

	dot = DotProduct( nvf, ovf );

	if ( forwhom->client )
	{
		forwhom->client->ps.viewangles[PITCH] = dot * pitch;
		forwhom->client->ps.viewangles[ROLL] = ((1-Q_fabs(dot)) * pitch * mod);
		oldmins2 = forwhom->r.mins[2];
		forwhom->r.mins[2] = -24 + 12 * fabs(forwhom->client->ps.viewangles[PITCH])/180.0f;
		//FIXME: if it gets bigger, move up
		if ( oldmins2 > forwhom->r.mins[2] )
		{//our mins is now lower, need to move up
			//FIXME: trace?
			forwhom->client->ps.origin[2] += (oldmins2 - forwhom->r.mins[2]);
			forwhom->r.currentOrigin[2] = forwhom->client->ps.origin[2];
			trap_LinkEntity( forwhom );
		}
	}
	else
	{
		forwhom->r.currentAngles[PITCH] = dot * pitch;
		forwhom->r.currentAngles[ROLL] = ((1-Q_fabs(dot)) * pitch * mod);
	}
}
示例#26
0
void Fog (edict_t *ent) //vec3_t viewpoint)
{
	edict_t	*triggerfog;
	edict_t	*player = ent; //&g_edicts[1];
	vec3_t	viewpoint;

	if (!gl_driver || !vid_ref)
		return;

	if (deathmatch->value || coop->value)
		return;

	if (!player->client || player->is_bot)
		return;

	VectorCopy(player->s.origin, viewpoint);
	viewpoint[2] += ent->viewheight;

	//Knightmare- also ref_kmgl.dll
	if(stricmp(vid_ref->string,"gl") && stricmp(vid_ref->string,"kmgl"))
	{
		last_software_frame = level.framenum;
		level.active_fog = 0;
		return;
	}

	InTriggerFog = false;
	if(level.trigger_fogs)
	{
		int i;
		int trigger;
		trigger=0;
		for(i=1; i<level.fogs; i++)
		{
			if(!gfogs[i].Trigger) continue;
			if(!gfogs[i].ent->inuse) continue;
			if(!(gfogs[i].ent->spawnflags & FOG_ON)) continue;
			if(viewpoint[0] < gfogs[i].ent->absmin[0]) continue;
			if(viewpoint[0] > gfogs[i].ent->absmax[0]) continue;
			if(viewpoint[1] < gfogs[i].ent->absmin[1]) continue;
			if(viewpoint[1] > gfogs[i].ent->absmax[1]) continue;
			if(viewpoint[2] < gfogs[i].ent->absmin[2]) continue;
			if(viewpoint[2] > gfogs[i].ent->absmax[2]) continue;
			trigger = i;
			break;
		}
		if(trigger)
		{
			InTriggerFog = true;
			triggerfog = gfogs[trigger].ent;

			if(level.last_active_fog != trigger+1)
			{
				if(triggerfog->delay)
					init_trigger_fog_delay(triggerfog);
				else
					memcpy(&level.fog,&gfogs[trigger],sizeof(fog_t));
				level.active_fog = trigger+1;
			}
			else if(triggerfog->delay)
				memcpy(&level.fog,&trig_fade_fog,sizeof(fog_t));
		}
		else
		{
			InTriggerFog = false;
			level.active_fog = level.active_target_fog;
			// if we are just coming out of a trigger_fog, force
			// level.fog to last active target_fog values
			if(level.active_fog && level.last_active_fog && gfogs[level.last_active_fog-1].Trigger)
			{
				edict_t	*ent = gfogs[level.active_fog-1].ent;
				if(ent && (ent->think == fog_fade))
					ent->think(ent);
				else
					memcpy(&level.fog,&gfogs[level.active_fog-1],sizeof(fog_t));
			}
		}
	}
	
	if (!level.active_fog)
	{
		if (level.last_active_fog)
			Fog_Off();
		level.last_active_fog = 0;
		return;
	}
	
	pfog = &level.fog;
	if((pfog->Density1 != pfog->Density2) && (game.maxclients == 1) && (pfog->Model))
	{
		float	density;
		float	dp;
		vec3_t	vp;

		AngleVectors(player->client->ps.viewangles,vp,0,0);
		dp = DotProduct(pfog->Dir,vp) + 1.0;
		density = ((pfog->Density1*dp) + (pfog->Density2*(2.0-dp)))/2.;
		if(pfog->Density != density)
		{
			pfog->Density = density;
		}
	}
	GLFog();
	level.last_active_fog = level.active_fog;
}
示例#27
0
edict_t	*LookingAt(edict_t *ent, int filter, vec3_t endpos, float *range)
{
    edict_t		*who;
    edict_t		*trigger[MAX_EDICTS];
    edict_t		*ignore;
    trace_t		tr;
    vec_t		r;
    vec3_t      end, forward, start;
    vec3_t		dir, entp, mins, maxs;
    int			i, num;

    if(!ent->client)
    {
        if(endpos) VectorClear(endpos);
        if(range) *range = 0;
        return NULL;
    }
    VectorClear(end);
    if (ent->client->chasetoggle)
    {
        AngleVectors(ent->client->v_angle, forward, NULL, NULL);
        VectorCopy(ent->client->chasecam->s.origin,start);
        ignore = ent->client->chasecam;
    }
    else if(ent->client->spycam)
    {
        AngleVectors(ent->client->ps.viewangles, forward, NULL, NULL);
        VectorCopy(ent->s.origin,start);
        ignore = ent->client->spycam;
    }
    else
    {
        AngleVectors(ent->client->v_angle, forward, NULL, NULL);
        VectorCopy(ent->s.origin, start);
        start[2] += ent->viewheight;
        ignore = ent;
    }

    VectorMA(start, 8192, forward, end);

    /* First check for looking directly at a pickup item */
    VectorSet(mins,-4096,-4096,-4096);
    VectorSet(maxs, 4096, 4096, 4096);
    num = gi.BoxEdicts (mins, maxs, trigger, MAX_EDICTS, AREA_TRIGGERS);
    for (i=0 ; i<num ; i++)
    {
        who = trigger[i];
        if (!who->inuse)
            continue;
        if (!who->item)
            continue;
        if (!visible(ent,who))
            continue;
        if (!infront(ent,who))
            continue;
        VectorSubtract(who->s.origin,start,dir);
        r = VectorLength(dir);
        VectorMA(start, r, forward, entp);
        if(entp[0] < who->s.origin[0] - 17) continue;
        if(entp[1] < who->s.origin[1] - 17) continue;
        if(entp[2] < who->s.origin[2] - 17) continue;
        if(entp[0] > who->s.origin[0] + 17) continue;
        if(entp[1] > who->s.origin[1] + 17) continue;
        if(entp[2] > who->s.origin[2] + 17) continue;
        if(endpos)
            VectorCopy(who->s.origin,endpos);
        if (range)
            *range = r;
        return who;
    }

    tr = gi.trace (start, NULL, NULL, end, ignore, MASK_SHOT);
    if (tr.fraction == 1.0)
    {
        // too far away
        gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0);
        return NULL;
    }
    if(!tr.ent)
    {
        // no hit
        gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0);
        return NULL;
    }
    if(!tr.ent->classname)
    {
        // should never happen
        gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0);
        return NULL;
    }

    if((strstr(tr.ent->classname,"func_") != NULL) && (filter & LOOKAT_NOBRUSHMODELS))
    {
        // don't hit on brush models
        gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0);
        return NULL;
    }
    if((Q_stricmp(tr.ent->classname,"worldspawn") == 0) && (filter & LOOKAT_NOWORLD))
    {
        // world brush
        gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/talk1.wav"), 1, ATTN_NORM, 0);
        return NULL;
    }
    if(endpos) {
        endpos[0] = tr.endpos[0];
        endpos[1] = tr.endpos[1];
        endpos[2] = tr.endpos[2];
    }
    if(range) {
        VectorSubtract(tr.endpos,start,start);
        *range = VectorLength(start);
    }
    return tr.ent;
}
示例#28
0
void SP_target_fog (edict_t *self)
{
	fog_t *fog;

	if ( !allow_fog->value )
	{
		G_FreeEdict(self);
		return;
	}
	if (deathmatch->value || coop->value)
	{
		G_FreeEdict(self);
		return;
	}

	self->class_id = ENTITY_TARGET_FOG;

	if(!level.fogs) level.fogs = 1;   // 1st fog reserved for console commands

	if(level.fogs >= MAX_FOGS)
	{
		gi.dprintf("Maximum number of fogs exceeded!\n");
		G_FreeEdict(self);
		return;
	}

	if( self->delay < 0.)
		self->delay = 0.;

	self->fog_index = level.fogs+1;
	fog = &gfogs[level.fogs];
	fog->Trigger = false;
	fog->Model   = self->fog_model;
	if(fog->Model < 0 || fog->Model > 2) fog->Model = 0;
	fog->GL_Model = GLModels[fog->Model];
	VectorCopy(self->fog_color,fog->Color);
	if(self->spawnflags & FOG_TURNOFF)
	{
		fog->Near     = 4999;
		fog->Far      = 5000;
		fog->Density  = 0;
		fog->Density1 = 0;
		fog->Density2 = 0;
	}
	else
	{
		fog->Near     = self->fog_near;
		fog->Far      = self->fog_far;
		fog->Density  = self->fog_density;
		fog->Density1 = self->fog_density;
		if(self->density == 0.)
			self->density = self->fog_density;
		else if(self->density < 0.)
			self->density = 0.;
		fog->Density2= self->density;
	}
	AngleVectors(self->s.angles,fog->Dir,0,0);
	fog->ent = self;
	level.fogs++;
	self->use = target_fog_use;
	gi.linkentity(self);

	if(self->spawnflags & FOG_ON)
	{
		self->spawnflags &= ~FOG_ON;
		target_fog_use(self,NULL,NULL);
	}
}
示例#29
0
void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles, qboolean spit ) {
    gentity_t	*tent;

    // use temp events at source and destination to prevent the effect
    // from getting dropped by a second player event
    /*freeze
    	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
    freeze*/
    if ( (g_gametype.integer == GT_FREEZE && !is_spectator( player->client )) ||
            (g_gametype.integer != GT_FREEZE && player->client->sess.sessionTeam != TEAM_SPECTATOR) ) {
//freeze
        tent = G_TempEntity( player->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
        tent->s.clientNum = player->s.clientNum;

        tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN );
        tent->s.clientNum = player->s.clientNum;
    }

    // unlink to make sure it can't possibly interfere with G_KillBox
    //player->relink = 0;
    trap_UnlinkEntity (player);

    VectorCopy ( origin, player->client->ps.origin );
    player->client->ps.origin[2] += 1;

    // spit the player out
    if (spit == qtrue) {
        AngleVectors( angles, player->client->ps.velocity, NULL, NULL );
        VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity );
        player->client->ps.pm_time = 160;		// hold time
        player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
    }

    // toggle the teleport bit so the client knows to not lerp
    player->client->ps.eFlags ^= EF_TELEPORT_BIT;

//unlagged - backward reconciliation #3
    // we don't want players being backward-reconciled back through teleporters
    G_ResetHistory( player );
//unlagged - backward reconciliation #3

    // set angles
    if (player->client->pers.fixedTeleporterAngles == qfalse)
        SetClientViewAngle( player, angles );

    // kill anything at the destination
    /*freeze
    	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
    freeze*/
    if ( (g_gametype.integer == GT_FREEZE && !is_spectator( player->client )) ||
            (g_gametype.integer != GT_FREEZE && player->client->sess.sessionTeam != TEAM_SPECTATOR) ) {
//freeze
        G_KillBox (player);
    }

    // save results of pmove
    BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue );

    // use the precise origin for linking
    VectorCopy( player->client->ps.origin, player->r.currentOrigin );

    /*freeze
    	if ( player->client->sess.sessionTeam != TEAM_SPECTATOR ) {
    freeze*/
    if ( (g_gametype.integer == GT_FREEZE && !is_spectator( player->client )) ||
            (g_gametype.integer != GT_FREEZE && player->client->sess.sessionTeam != TEAM_SPECTATOR) ) {
//freeze
        trap_LinkEntity (player);
    }
}
示例#30
0
//---------------------------------------------------------
void WP_FireBryarPistol( gentity_t *ent, qboolean alt_fire )
//---------------------------------------------------------
{
	vec3_t	start;
	int		damage = !alt_fire ? weaponData[WP_BRYAR_PISTOL].damage : weaponData[WP_BRYAR_PISTOL].altDamage;
	int		velocity = !alt_fire ? weaponData[WP_BRYAR_PISTOL].velocity : weaponData[WP_BRYAR_PISTOL].altVelocity;

	if (ent->s.number != 0 && ent->client->NPC_class != CLASS_BOBAFETT && ent->client->NPC_class != CLASS_MANDA)
	{
		damage *= weaponData[WP_BRYAR_PISTOL].npcDmgMult;
	}

	VectorCopy( muzzle, start );
	WP_TraceSetStart( ent, start, vec3_origin, vec3_origin );//make sure our start point isn't on the other side of a wall

	if ( !(ent->client->ps.forcePowersActive&(1<<FP_SEE))
		|| ent->client->ps.forcePowerLevel[FP_SEE] < FORCE_LEVEL_2 )
	{//force sight 2+ gives perfect aim
		//FIXME: maybe force sight level 3 autoaims some?
		if ( ent->NPC && ent->NPC->currentAim < 5 )
		{
			vec3_t	angs;

			vectoangles( forwardVec, angs );

			if ( ent->client->NPC_class == CLASS_IMPWORKER )
			{//*sigh*, hack to make impworkers less accurate without affecteing imperial officer accuracy
				angs[PITCH] += ( Q_flrand(-1.0f, 1.0f) * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f));//was 0.5f
				angs[YAW]	+= ( Q_flrand(-1.0f, 1.0f) * (BLASTER_NPC_SPREAD+(6-ent->NPC->currentAim)*0.25f));//was 0.5f
			}
			else
			{
				angs[PITCH] += ( Q_flrand(-1.0f, 1.0f) * ((5-ent->NPC->currentAim)*0.25f) );
				angs[YAW]	+= ( Q_flrand(-1.0f, 1.0f) * ((5-ent->NPC->currentAim)*0.25f) );
			}

			AngleVectors( angs, forwardVec, NULL, NULL );
		}
	}

	WP_MissileTargetHint(ent, start, forwardVec);

	gentity_t	*missile = CreateMissile( start, forwardVec, velocity, 10000, ent, alt_fire );

	missile->classname = "bryar_proj";
	if ( ent->s.weapon == WP_BLASTER_PISTOL
		|| ent->s.weapon == WP_JAWA )
	{//*SIGH*... I hate our weapon system...
		missile->s.weapon = ent->s.weapon;
	}
	else
	{
		missile->s.weapon = WP_BRYAR_PISTOL;
	}

	if ( alt_fire )
	{
		int count = ( level.time - ent->client->ps.weaponChargeTime ) / BRYAR_CHARGE_UNIT;

		if ( count < 1 )
		{
			count = 1;
		}
		else if ( count > 5 )
		{
			count = 5;
		}

		damage *= count;
		missile->count = count; // this will get used in the projectile rendering code to make a beefier effect
	}

//	if ( ent->client && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > 0 && ent->client->ps.powerups[PW_WEAPON_OVERCHARGE] > cg.time )
//	{
//		// in overcharge mode, so doing double damage
//		missile->flags |= FL_OVERCHARGED;
//		damage *= 2;
//	}

	missile->damage = damage;
	missile->dflags = DAMAGE_DEATH_KNOCKBACK;

	if ( alt_fire )
	{
		missile->methodOfDeath = MOD_BRYAR_ALT;
	}
	else
	{
		missile->methodOfDeath = MOD_BRYAR;
	}

	missile->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER;

	// we don't want it to bounce forever
	missile->bounceCount = 8;

	if ( ent->weaponModel[1] > 0 )
	{//dual pistols, toggle the muzzle point back and forth between the two pistols each time he fires
		ent->count = (ent->count)?0:1;
	}
}