예제 #1
0
void	dbg_draw_viewport( const T &cam_info, float _viewport_near )
{
	
	VERIFY( _viewport_near > 0.f );
	const Fvector near_plane_center = Fvector().mad( cam_info.Position(), cam_info.Direction(), _viewport_near );
	float h_w, h_h;
	viewport_size ( _viewport_near, cam_info, h_w, h_h );
	const Fvector right	= Fvector().mul( cam_info.Right(), h_w );
	const Fvector up	= Fvector().mul( cam_info.Up(), h_h );

	
	const Fvector	top_left = Fvector().sub( near_plane_center,  right ).add( up );
	const Fvector	top_right = Fvector().add( near_plane_center,  right ).add( up );
	const Fvector	bottom_left = Fvector().sub( near_plane_center,  right ).sub( up );
	const Fvector	bottom_right = Fvector().add( near_plane_center,  right ).sub( up );
	
	DBG_DrawLine( cam_info.Position(), top_left, D3DCOLOR_XRGB(255, 0, 0 ) );
	DBG_DrawLine( cam_info.Position(), top_right, D3DCOLOR_XRGB(255, 0, 0 ) );
	DBG_DrawLine( cam_info.Position(), bottom_left, D3DCOLOR_XRGB(255, 0, 0 ) );
	DBG_DrawLine( cam_info.Position(), bottom_right, D3DCOLOR_XRGB(255, 0, 0 ) );

	DBG_DrawLine( top_right, top_left, D3DCOLOR_XRGB(255, 0, 0 ) );
	DBG_DrawLine( bottom_right, top_right, D3DCOLOR_XRGB(255, 0, 0 ) );
	DBG_DrawLine( top_left, bottom_left, D3DCOLOR_XRGB(255, 0, 0 ) );
	DBG_DrawLine( bottom_left, bottom_right, D3DCOLOR_XRGB(255, 0, 0 ) );

}
예제 #2
0
bool CIKFoot::make_shift( Fmatrix &xm,const Fvector &cl_point, bool collide, const Fplane &p, const Fvector &pick_dir )const
{
	Fvector shift = pick_dir;

	//Fvector toe; ToePosition( toe ); xm.transform_tiny( toe );
	Fvector point;
	xm.transform_tiny( point, cl_point );
	float dot = p.n.dotproduct( shift );
	if( _abs( dot ) < min_dot )
	{
		shift.add( Fvector( ).mul( p.n, min_dot - _abs( dot ) ) );
		dot = p.n.dotproduct( shift );
	}
	VERIFY( !fis_zero( dot ) );
	float shift_m = ( -p.d - p.n.dotproduct( point ) )/dot;
	if(collide && shift_m > 0.f )
		return false;
	clamp( shift_m, -collide_dist, collide_dist );
	shift.mul( shift_m );
	xm.c.add( shift );
#if	0
	if(shift_m > 0.f)
	{
		DBG_OpenCashedDraw();
		DBG_DrawLine( toe, Fvector().add( toe, shift ), D3DCOLOR_XRGB( 255, 255, 255 )  );
		DBG_ClosedCashedDraw( 1000 );
	}
#endif
	return true;
}
예제 #3
0
void object_shift::	dbg_draw			( const Fmatrix	&current_pos, const extrapolation::points &predict , const Fvector& start ) const
{
	Fvector p0;
	current_pos.transform_tiny( p0, start );
	Fmatrix predicted_pos;
	predict.extrapolate( predicted_pos, taget_time );
	Fvector p1;
	predicted_pos.transform_tiny( p1, start );
	const	u16 nb_points	= 200;

	float time_global = Device.fTimeGlobal;
	if( time_global > taget_time )
				time_global = taget_time;

	float time = taget_time - time_global;
	float time_passed = time_global - current_time;
	if(fis_zero(time))
		return;

	float time_quant = ( time ) / nb_points;

	const Fvector vadd = Fvector().sub( p1, p0 ).mul( 1.f/nb_points );
	for( u16 i = 0; i < nb_points; ++i )
	{
		float fshift0 = current + delta_shift( time_passed + time_quant * i );
		float fshift1 = current + delta_shift( time_passed + time_quant * ( i + 1 ) );
		Fvector	v0 = Fvector().add( p0, Fvector().mul( vadd, float( i ) ) ).add( Fvector().set( 0, fshift0, 0 ) );
		Fvector	v1 = Fvector().add( p0, Fvector().mul( vadd, float( i + 1 ) ) ).add( Fvector().set( 0, fshift1, 0 ) );

		DBG_DrawLine(
			v0,
			v1, 
			D3DCOLOR_XRGB( 0, 255, 0 ) );
	}
	
	float	start_shift = current + delta_shift( time_passed );
	float	end_shift = current + delta_shift( time_passed + time );
	DBG_DrawLine(
		Fvector().add( p0, Fvector().set( 0, start_shift, 0 ) )	,
		Fvector().add( p1, Fvector().set( 0, end_shift, 0 ) ),
			D3DCOLOR_XRGB( 255, 0, 0 ) );
}
예제 #4
0
bool Pick( ik_pick_result &r, const ik_pick_query &q , CObject* ignore_object)
{
	VERIFY( q.is_valid() );

	float range = q.range();
	
	collide::rq_result	R;
	bool collided = false;
	Fvector pos = q.pos();

	while( g_pGameLevel->ObjectSpace.RayPick( pos, q.dir(), range, collide::rqtBoth, R, ignore_object ) )
	{
		
		Fvector next_pos	= pos;
		float	next_range	= range;

		collided = get_plane( r, next_pos, next_range , R, range, pos,  q.dir() );
		if( collided )
			break;

		range	= next_range;
		pos		= next_pos;
		if( range < EPS )
			break;
	}

#ifdef DEBUG
	if( ph_dbg_draw_mask1.test( phDbgDrawIKCollision ) && collided && !R.O )
	{
		CDB::TRI	*tri	= Level( ).ObjectSpace.GetStaticTris( ) + R.element;
		Fvector p = q.pos();p.add( Fvector( ).mul( q.dir(), range ) );
		DBG_DrawLine(pos,p,D3DCOLOR_XRGB( 255, 0, 0 ) );
		if( tri )
		{
			DBG_DrawTri( tri,Level( ).ObjectSpace.GetStaticVerts( ), D3DCOLOR_XRGB( 255, 0, 0 ) );
		}
	}
#endif
	return collided;
}
예제 #5
0
파일: Actor.cpp 프로젝트: OLR-xray/XRay-NEW
void	CActor::Hit							(SHit* pHDS)
{
	pHDS->aim_bullet = false;

	SHit HDS = *pHDS;
	if( HDS.hit_type<ALife::eHitTypeBurn || HDS.hit_type >= ALife::eHitTypeMax )
	{
		string256	err;
		sprintf		(err, "Unknown/unregistered hit type [%d]", HDS.hit_type);
		R_ASSERT2	(0, err );
	
	}
#ifdef DEBUG
if(ph_dbg_draw_mask.test(phDbgCharacterControl))
{
	DBG_OpenCashedDraw();
	Fvector to;to.add(Position(),Fvector().mul(HDS.dir,HDS.phys_impulse()));
	DBG_DrawLine(Position(),to,D3DCOLOR_XRGB(124,124,0));
	DBG_ClosedCashedDraw(500);
}
#endif
	bool bPlaySound = true;
	if (!g_Alive()) bPlaySound = false;

	if (!IsGameTypeSingle() && !g_pGamePersistent->bDedicatedServer)
	{
		game_PlayerState* ps = Game().GetPlayerByGameID(ID());
		if (ps && ps->testFlag(GAME_PLAYER_FLAG_INVINCIBLE))
		{
			bPlaySound = false;
			if (Device.dwFrame != last_hit_frame &&
				HDS.bone() != BI_NONE)
			{		
				// вычислить позицию и направленность партикла
				Fmatrix pos; 

				CParticlesPlayer::MakeXFORM(this,HDS.bone(),HDS.dir,HDS.p_in_bone_space,pos);

				// установить particles
				CParticlesObject* ps = NULL;

				if (eacFirstEye == cam_active && this == Level().CurrentEntity())
					ps = CParticlesObject::Create(invincibility_fire_shield_1st,TRUE);
				else
					ps = CParticlesObject::Create(invincibility_fire_shield_3rd,TRUE);

				ps->UpdateParent(pos,Fvector().set(0.f,0.f,0.f));
				GamePersistent().ps_needtoplay.push_back(ps);
			};
		};
		 

		last_hit_frame = Device.dwFrame;
	};

	if(	!g_pGamePersistent->bDedicatedServer	&& 
		!sndHit[HDS.hit_type].empty()			&& 
		(ALife::eHitTypeTelepatic != HDS.hit_type))
	{
		ref_sound& S = sndHit[HDS.hit_type][Random.randI(sndHit[HDS.hit_type].size())];
		bool b_snd_hit_playing = sndHit[HDS.hit_type].end() != std::find_if(sndHit[HDS.hit_type].begin(), sndHit[HDS.hit_type].end(), playing_pred());

		if(ALife::eHitTypeExplosion == HDS.hit_type)
		{
			if (this == Level().CurrentControlEntity())
			{
				S.set_volume(10.0f);
				if(!m_sndShockEffector){
					m_sndShockEffector = xr_new<SndShockEffector>();
					m_sndShockEffector->Start(this, float(S._handle()->length_ms()), HDS.damage() );
				}
			}
			else
				bPlaySound = false;
		}
		if (bPlaySound && !b_snd_hit_playing) 
		{
			Fvector point		= Position();
			point.y				+= CameraHeight();
			S.play_at_pos		(this, point);
		};
	}

	
	//slow actor, only when he gets hit
	if(HDS.hit_type == ALife::eHitTypeWound || HDS.hit_type == ALife::eHitTypeStrike)
	{
		hit_slowmo				= HDS.damage();
		clamp					(hit_slowmo,0.0f,1.f);
	}
	else
		hit_slowmo = 0.f;
	//---------------------------------------------------------------
	if (Level().CurrentViewEntity() == this && !g_pGamePersistent->bDedicatedServer && HDS.hit_type == ALife::eHitTypeFireWound)
	{
		CObject* pLastHitter = Level().Objects.net_Find(m_iLastHitterID);
		CObject* pLastHittingWeapon = Level().Objects.net_Find(m_iLastHittingWeaponID);
		HitSector(pLastHitter, pLastHittingWeapon);
	};

	if ((mstate_real&mcSprint) && Level().CurrentControlEntity() == this && 
		HDS.hit_type != ALife::eHitTypeTelepatic &&
		HDS.hit_type != ALife::eHitTypeRadiation 
		)
	{
//		mstate_real	&=~mcSprint;
		mstate_wishful	&=~mcSprint;
	};
	if(!g_pGamePersistent->bDedicatedServer)
	{
		HitMark			(HDS.damage(), HDS.dir, HDS.who, HDS.bone(), HDS.p_in_bone_space, HDS.impulse, HDS.hit_type);
	}

	switch (GameID())
	{
	case GAME_SINGLE:		
		{
			float hit_power	= HitArtefactsOnBelt(HDS.damage(), HDS.hit_type);

			if (GodMode())//psActorFlags.test(AF_GODMODE))
			{
				HDS.power = 0.0f;
//				inherited::Hit(0.f,dir,who,element,position_in_bone_space,impulse, hit_type);
				inherited::Hit(&HDS);
				return;
			}
			else 
			{
				//inherited::Hit		(hit_power,dir,who,element,position_in_bone_space, impulse, hit_type);
				HDS.power = hit_power;
				inherited::Hit(&HDS);
			};
		}
		break;
	default:
		{
			m_bWasBackStabbed = false;
			if (HDS.hit_type == ALife::eHitTypeWound_2 && Check_for_BackStab_Bone(HDS.bone()))
			{
				// convert impulse into local coordinate system
				Fmatrix					mInvXForm;
				mInvXForm.invert		(XFORM());
				Fvector					vLocalDir;
				mInvXForm.transform_dir	(vLocalDir,HDS.dir);
				vLocalDir.invert		();

				Fvector a	= {0,0,1};
				float res = a.dotproduct(vLocalDir);
				if (res < -0.707)
				{
					game_PlayerState* ps = Game().GetPlayerByGameID(ID());
					if (!ps || !ps->testFlag(GAME_PLAYER_FLAG_INVINCIBLE))						
						m_bWasBackStabbed = true;
				}
			};
			
			float hit_power = 0;

			if (m_bWasBackStabbed) hit_power = 100000;
			else hit_power	= HitArtefactsOnBelt(HDS.damage(), HDS.hit_type);

			HDS.power = hit_power;
			inherited::Hit (&HDS);
			//inherited::Hit	(hit_power,dir,who,element,position_in_bone_space, impulse, hit_type, 0.0f);
		}		
		break;
	}
}
예제 #6
0
void CIKLimbsController::Calculate( )
{
	update_blend( m_legs_blend );

	Fmatrix &obj = m_object->XFORM( );
#ifdef	DEBUG
	if( ph_dbg_draw_mask1.test( phDbgDrawIKSHiftObject ) )
		_object_shift.dbg_draw( obj, _pose_extrapolation, Fvector().set( 0,2.5f,0));
#endif

	SCalculateData cd[max_size];



	xr_vector<CIKLimb>::iterator i, b = _bone_chains.begin(), e = _bone_chains.end();
	for( i = b ; e != i; ++i )
	{
		cd[i-b] = SCalculateData ( *i, obj );
		LimbCalculate( cd[i-b] );
	}

	IKinematics *K = m_object->Visual()->dcast_PKinematics( );
	u16 root = K->LL_GetBoneRoot( ) ;
	CBoneInstance &root_bi = K->LL_GetBoneInstance(root);

	BOOL sv_root_cb_ovwr = root_bi.callback_overwrite();
	BoneCallback sv_root_cb =		root_bi.callback();

	root_bi.set_callback( root_bi.callback_type(), 0, root_bi.callback_param(), TRUE );


	if( ik_shift_object  )//&& ! m_object->animation_movement_controlled( )
	{

			ShiftObject( cd );
	}

	const u16 sz =(u16)_bone_chains.size();
	for(u16 j = 0; sz > j; ++j )
		cd[j].m_limb->SetGoal( cd[j] );

	for(u16 j = 0; sz > j; ++j )
	{
		
		cd[j].m_limb->SolveBones( cd[j] );

#ifdef	DEBUG
	if( ph_dbg_draw_mask1.test( phDbgDrawIKPredict ) )
	{
		//IKinematics *K = m_object->Visual()->dcast_PKinematics( );
		u16 ref_bone_id = cd[j].m_limb->dbg_ref_bone_id();
		Fmatrix m =Fmatrix().mul( obj, K->LL_GetTransform( ref_bone_id ) );
		Fvector toe;
		cd[j].m_limb->dbg_ik_foot().ToePosition( toe );
		m.transform_tiny( toe );
		DBG_DrawLine( toe, Fvector().add( toe, Fvector().set( 0, -_object_shift.shift(), 0 ) ), D3DCOLOR_XRGB( 255, 0, 0 )  );
	}
#endif
	}
	ObjectShift( 0, cd );
	


	root_bi.set_callback( root_bi.callback_type(), sv_root_cb, root_bi.callback_param(), sv_root_cb_ovwr );

}
예제 #7
0
bool	CPhysicObject::get_door_vectors	( Fvector& closed, Fvector& open ) const
{
	VERIFY(Visual());
	IKinematics *K = Visual()->dcast_PKinematics();
	VERIFY(K);
	u16 door_bone = K->LL_BoneID("door");
	if( door_bone==BI_NONE )
		return false;
	const CBoneData &bd = K->LL_GetData( door_bone );
	const SBoneShape &shape = bd.shape;
	if( shape.type != SBoneShape::stBox )
		return false;

	if( shape.flags.test( SBoneShape::sfNoPhysics ) )
		return false;
	
	Fmatrix start_bone_pos;
	K->Bone_GetAnimPos( start_bone_pos, door_bone, u8(-1), true );
	
	Fmatrix start_pos = Fmatrix().mul_43( XFORM(), start_bone_pos );
	
	const Fobb &box = shape.box;

	Fvector center_pos;
	start_pos.transform_tiny( center_pos, box.m_translate );

	Fvector door_dir;  start_pos.transform_dir(door_dir, box.m_rotate.i );
	Fvector door_dir_local =  box.m_rotate.i ;
	//Fvector door_dir_bone; start_bone_pos.transform_dir(door_dir_bone, box.m_rotate.i );

	
	const Fvector det_vector = Fvector().sub( center_pos, start_pos.c  );
	
	if( door_dir.dotproduct( det_vector ) < 0.f )
	{
		door_dir.invert();
		door_dir_local.invert();
		//door_dir_bone.invert();
	}

	const SJointIKData &joint = bd.IK_data;

	if( joint.type != jtJoint )
		return false;
	const Fvector2& limits = joint.limits[1].limit;

	//if( limits.y < EPS ) //limits.y - limits.x < EPS
	//	return false;

	if( M_PI - limits.y < EPS && M_PI + limits.x < EPS )
		return false;

	Fmatrix to_hi = Fmatrix().rotateY( -limits.x  ); 
	to_hi.transform_dir( open, door_dir_local );

	Fmatrix to_lo = Fmatrix().rotateY(  -limits.y  );
	to_lo.transform_dir( closed, door_dir_local );

	start_pos.transform_dir(open);
	start_pos.transform_dir(closed);

	//DBG_OpenCashedDraw( );

#ifdef	DEBUG
if(dbg_draw_doors)
{
	DBG_DrawMatrix( Fidentity, 10.0f );

	DBG_DrawMatrix( XFORM(), .5f, 100 );

	DBG_DrawMatrix( start_pos, 0.2f,100 );

	const Fvector pos = start_pos.c.add( Fvector().set(0,0.2f,0) );
	const Fvector pos1 = start_pos.c.add( Fvector().set(0,0.3f,0) );

	DBG_DrawLine( pos, Fvector( ).add( pos, open ), D3DCOLOR_XRGB( 0, 255, 0 ) );
	DBG_DrawLine( pos, Fvector( ).add( pos, closed ), D3DCOLOR_XRGB( 255, 0, 0 ) );

	DBG_DrawLine( pos1, Fvector( ).add( pos1, det_vector ), D3DCOLOR_XRGB( 255, 255, 0 ) );
}
#endif
	//DBG_ClosedCashedDraw( 50000000 );

	return true;
}
예제 #8
0
void character_hit_animation_controller::PlayHitMotion( const Fvector &dir, const Fvector &bone_pos, u16 bi, CEntityAlive &ea )const
{
	IRenderVisual *pV = ea.Visual( );
	IKinematicsAnimated* CA = smart_cast<IKinematicsAnimated*>( pV );
	IKinematics* K = smart_cast<IKinematics*>( pV );
	
	//play_cycle(CA,all_shift_down,1,block_times[6],1) ;
	if( !( K->LL_BoneCount( ) > bi ) )
		return;

	Fvector dr = dir;
	Fmatrix m;
	GetBaseMatrix( m, ea );

#ifdef DEBUG
	if( ph_dbg_draw_mask1.test( phDbgHitAnims ) )
	{
		DBG_OpenCashedDraw();
		DBG_DrawLine( m.c, Fvector( ).sub( m.c, Fvector( ).mul( dir, 1.5 ) ), D3DCOLOR_XRGB( 255, 0, 255 ) );
		DBG_ClosedCashedDraw( 1000 );
	}
#endif

	m.invert( );
	m.transform_dir( dr );
//
	Fvector hit_point;
	K->LL_GetTransform( bi ).transform_tiny( hit_point, bone_pos );
	ea.XFORM( ).transform_tiny( hit_point );
	m.transform_tiny( hit_point );
	Fvector torqu;		
	torqu.crossproduct( dr, hit_point );
	hit_point.x = 0;


	float rotational_ammount = hit_point.magnitude( ) * g_params.power_factor * g_params.rotational_power_factor;//_abs(torqu.x)
	
	if( torqu.x < 0 )
		play_cycle( CA, hit_downr, 3, block_blends[7], 1 ) ;
	else
		play_cycle( CA, hit_downl, 3, block_blends[6], 1 ) ;

	if( !IsEffected( bi, *K ) )
		return;
	if( torqu.x<0 )
		play_cycle( CA, turn_right, 2, block_blends[4], rotational_ammount ) ;
	else
		play_cycle( CA, turn_left, 2, block_blends[5], rotational_ammount ) ;

	//CA->LL_SetChannelFactor(3,rotational_ammount);

	dr.x = 0;
	dr.normalize_safe();


	dr.mul(g_params.power_factor);
	if( dr.y > g_params.side_sensitivity_threshold )
		play_cycle( CA, rthit_motion, 2, block_blends[0], _abs( dr.y ) ) ;
	else if( dr.y < -g_params.side_sensitivity_threshold )
		play_cycle( CA, lthit_motion, 2, block_blends[1], _abs( dr.y ) ) ;

	if( dr.z<0.f )
		play_cycle( CA, fvhit_motion, 2, block_blends[2], _abs(dr.z) ) ;
	else
		play_cycle( CA, bkhit_motion, 2, block_blends[3], _abs( dr.z ) ) ;

	CA->LL_SetChannelFactor( 2, g_params.anim_channel_factor );


}
예제 #9
0
float CExplosive::ExplosionEffect(collide::rq_results& storage, CExplosive*exp_obj,CPhysicsShellHolder*blasted_obj,  const Fvector &expl_centre, const float expl_radius) 
{
	
	const Fmatrix	&obj_xform=blasted_obj->XFORM();
	Fmatrix	inv_obj_form;inv_obj_form.invert(obj_xform);
	Fvector	local_exp_center;inv_obj_form.transform_tiny(local_exp_center,expl_centre);

	const Fbox &l_b1 = blasted_obj->BoundingBox();
	if(l_b1.contains(local_exp_center)) 
										return 1.f;
	Fvector l_c, l_d;l_b1.get_CD(l_c,l_d);
	float effective_volume=l_d.x*l_d.y*l_d.z;
	float max_s=effective_volume/(_min(_min(l_d.x,l_d.y),l_d.z));
	if(blasted_obj->PPhysicsShell()&&blasted_obj->PPhysicsShell()->isActive())
	{
		float ph_volume=blasted_obj->PPhysicsShell()->getVolume();
		if(ph_volume<effective_volume)effective_volume=ph_volume;
	}
	float effect=0.f;
#ifdef DEBUG
	if(ph_dbg_draw_mask.test(phDbgDrawExplosions))
	{
		Fmatrix dbg_box_m;dbg_box_m.set(obj_xform);
		dbg_box_m.c.set(l_c);obj_xform.transform(dbg_box_m.c);
		DBG_DrawOBB(dbg_box_m,l_d,D3DCOLOR_XRGB(255,255,0));
	}
#endif

	for(u16 i=0;i<TEST_RAYS_PER_OBJECT;++i){
		Fvector l_source_p,l_end_p;
		l_end_p.random_point(l_d);
		l_end_p.add(l_c);
		obj_xform.transform_tiny(l_end_p);
		GetRaySourcePos(exp_obj,expl_centre,l_source_p);
		Fvector l_local_source_p;inv_obj_form.transform_tiny(l_local_source_p,l_source_p);
		if(l_b1.contains(l_local_source_p))
		{
			effect+=1.f;continue;
		}
		Fvector l_dir; l_dir.sub(l_end_p,l_source_p);
		float mag=l_dir.magnitude();
		
		if(fis_zero(mag)) return 1.f;

		l_dir.mul(1.f/mag);
#ifdef DEBUG
			if(ph_dbg_draw_mask.test(phDbgDrawExplosions))
			{
			DBG_DrawPoint(l_source_p,0.1f,D3DCOLOR_XRGB(0,0,255));
			DBG_DrawPoint(l_end_p,0.1f,D3DCOLOR_XRGB(0,0,255));
			DBG_DrawLine(l_source_p,l_end_p,D3DCOLOR_XRGB(0,0,255));
			}
#endif
		
#ifdef DEBUG
		float l_S=effective_volume*(_abs(l_dir.dotproduct(obj_xform.i))/l_d.x+_abs(l_dir.dotproduct(obj_xform.j))/l_d.y+_abs(l_dir.dotproduct(obj_xform.k))/l_d.z);
		float add_eff=_sqrt(l_S/max_s)*TestPassEffect(l_source_p,l_dir,mag,expl_radius,storage,blasted_obj);
		effect+=add_eff;
		if(ph_dbg_draw_mask.test(phDbgDrawExplosions))
		{
			Msg("dist %f,effect R %f",mag,expl_radius);
			Msg("test pass effect %f",add_eff);
			Msg("S effect %f",_sqrt(l_S/max_s));
			Msg("dist/overlap effect, %f",add_eff/_sqrt(l_S/max_s));
		}
#else
		float l_S=effective_volume*(_abs(l_dir.dotproduct(obj_xform.i))/l_d.x+_abs(l_dir.dotproduct(obj_xform.j))/l_d.y+_abs(l_dir.dotproduct(obj_xform.k))/l_d.z);
		effect+=_sqrt(l_S/max_s)*TestPassEffect(l_source_p,l_dir,mag,expl_radius,storage,blasted_obj);
#endif

	}
#ifdef DEBUG
	if(ph_dbg_draw_mask.test(phDbgDrawExplosions))
	{
			Msg("damage effect %f",effect/TEST_RAYS_PER_OBJECT);
	}
#endif
	return effect/TEST_RAYS_PER_OBJECT;
	
}