Ejemplo n.º 1
0
void CTeamBaseZone::OnRender() 
{
	if(!bDebug) return;
	if (!(dbg_net_Draw_Flags.is_any((1<<3)))) return;
//	RCache.OnFrameEnd();
	Fvector l_half; l_half.set(.5f, .5f, .5f);
	Fmatrix l_ball, l_box;
	xr_vector<CCF_Shape::shape_def> &l_shapes = ((CCF_Shape*)CFORM())->Shapes();
	xr_vector<CCF_Shape::shape_def>::iterator l_pShape;
	
	for(l_pShape = l_shapes.begin(); l_shapes.end() != l_pShape; ++l_pShape) 
	{
		switch(l_pShape->type)
		{
		case 0:
			{
                Fsphere &l_sphere = l_pShape->data.sphere;
				l_ball.scale(l_sphere.R, l_sphere.R, l_sphere.R);
				Fvector l_p; XFORM().transform(l_p, l_sphere.P);
				l_ball.translate_add(l_p);
				Level().debug_renderer().draw_ellipse(l_ball, D3DCOLOR_XRGB(0,255,255));
			}
			break;
		case 1:
			{
				l_box.mul(XFORM(), l_pShape->data.box);
				Level().debug_renderer().draw_obb(l_box, l_half, D3DCOLOR_XRGB(0,255,255));
			}
			break;
		}
	}
}
Ejemplo n.º 2
0
void CMosquitoBald::Affect(SZoneObjectInfo* O) 
{
	CPhysicsShellHolder *pGameObject = smart_cast<CPhysicsShellHolder*>(O->object);
	if(!pGameObject) return;

	if(O->zone_ignore) return;

	Fvector P; 
	XFORM().transform_tiny(P,CFORM()->getSphere().P);

	Fvector hit_dir; 
	hit_dir.set(	::Random.randF(-.5f,.5f), 
					::Random.randF(.0f,1.f), 
					::Random.randF(-.5f,.5f)); 
	hit_dir.normalize();

	Fvector position_in_bone_space;

	VERIFY(!pGameObject->getDestroy());

	float dist = pGameObject->Position().distance_to(P) - pGameObject->Radius();
	float power = Power(dist>0.f?dist:0.f, Radius());
	float impulse = m_fHitImpulseScale*power*pGameObject->GetMass();

	if(power > 0.01f) 
	{
		position_in_bone_space.set(0.f,0.f,0.f);
		CreateHit(pGameObject->ID(),ID(),hit_dir,power,0,position_in_bone_space,impulse,m_eHitTypeBlowout);
		PlayHitParticles(pGameObject);
	}
}
Ejemplo n.º 3
0
void CRadioactiveZone::Affect(SZoneObjectInfo* O) 
{
	// вермя срабатывания не чаще, чем заданный период
	if(m_dwDeltaTime < m_dwPeriod) return;
//.	m_dwDeltaTime = 0;
	
	CGameObject *GO = O->object;
	
	if(GO) 
	{
		Fvector pos; 
		XFORM().transform_tiny(pos,CFORM()->getSphere().P);

#ifdef DEBUG		
		char pow[255]; 
		sprintf(pow, "zone hit. %.3f", Power(GO->Position().distance_to(pos)));
		if(bDebug) Msg("%s %s", *GO->cName(), pow);
#endif

		Fvector dir; 
		dir.set(0,0,0);
	
		Fvector position_in_bone_space;
		float power = (GameID() == GAME_SINGLE) ? Power(GO->Position().distance_to(pos)) : 0.0f;
		float impulse = 0.f;
		if(power > EPS) 
		{
//.			m_dwDeltaTime = 0;
			position_in_bone_space.set(0.f,0.f,0.f);

			CreateHit(GO->ID(),ID(),dir,power,BI_NONE,position_in_bone_space,impulse,ALife::eHitTypeRadiation);
		}
	}
}
Ejemplo n.º 4
0
float CAmebaZone::distance_to_center(CObject* O)
{
	Fvector P; 
	XFORM().transform_tiny(P,CFORM()->getSphere().P);
	Fvector OP;OP.set(O->Position());
	return _sqrt((P.x-OP.x)*(P.x-OP.x)+(P.x-OP.x)*(P.x-OP.x));
}
Ejemplo n.º 5
0
void CCustomZone::PlayBoltEntranceParticles()
{

	CCF_Shape* Sh		= (CCF_Shape*)CFORM();
	const Fmatrix& XF	= XFORM();
	Fmatrix				PXF;
	xr_vector<CCF_Shape::shape_def>& Shapes = Sh->Shapes();
	Fvector				sP0, sP1, vel;

	CParticlesObject* pParticles = NULL;

	xr_vector<CCF_Shape::shape_def>::iterator it = Shapes.begin();
	xr_vector<CCF_Shape::shape_def>::iterator it_e = Shapes.end();
	
	for(;it!=it_e;++it)
	{
		CCF_Shape::shape_def& s = *it;
		switch (s.type)
		{
		case 0: // sphere
			{
			sP0						= s.data.sphere.P;
			XF.transform_tiny		(sP0);

			
			
			float ki				= 10.0f * s.data.sphere.R;
			float c					= 2.0f * s.data.sphere.R;

			float quant_h			= (PI_MUL_2/float(ki))*c;
			float quant_p			= (PI_DIV_2/float(ki));

			for(float i=0; i<ki; ++i)
			{
				vel.setHP				(	::Random.randF(quant_h/2.0f, quant_h)*i, 
											::Random.randF(quant_p/2.0f, quant_p)*i
										);

				vel.mul					(s.data.sphere.R);

				sP1.add					(sP0, vel);

				PXF.identity			();
				PXF.k.normalize			(vel);
				Fvector::generate_orthonormal_basis(PXF.k, PXF.j, PXF.i);

				PXF.c					= sP1;

				pParticles				= CParticlesObject::Create(m_sBoltEntranceParticles.c_str(), TRUE);
				pParticles->UpdateParent(PXF,vel);
				pParticles->Play		(false);
			}
			}break;
		case 1: // box
			break;
		}
	}

}
Ejemplo n.º 6
0
void CTeamBaseZone::shedule_Update(u32 dt)
{
	inherited::shedule_Update	(dt);
	
	const Fsphere				&s = CFORM()->getSphere();
	Fvector						P;
	XFORM().transform_tiny		(P,s.P);
	feel_touch_update			(P,s.R);
}
Ejemplo n.º 7
0
BOOL CRadioactiveZone::feel_touch_contact(CObject* O)
{

	CActor* A = smart_cast<CActor*>(O);
	if ( A )
	{ 
		if (!((CCF_Shape*)CFORM())->Contact(O))		return	FALSE;
		return										A->feel_touch_on_contact(this);
	}else
		return										FALSE;
}
Ejemplo n.º 8
0
void CLevelChanger::shedule_Update(u32 dt)
{
	inherited::shedule_Update	(dt);

	const Fsphere				&s = CFORM()->getSphere();
	Fvector						P;
	XFORM().transform_tiny		(P,s.P);
	feel_touch_update			(P,s.R);

	update_actor_invitation		();
}
Ejemplo n.º 9
0
float CRadioactiveZone::nearest_shape_radius(SZoneObjectInfo* O)
{
	CCF_Shape* Sh		= (CCF_Shape*)CFORM();

	if(Sh->Shapes().size()==1)
	{
		return			Radius();
	}else
	{
		xr_vector<CCF_Shape::shape_def>& Shapes = Sh->Shapes();
		CCF_Shape::shape_def& s = Shapes[0];
		return s.data.sphere.R;
	}
}
Ejemplo n.º 10
0
BOOL CLevelChanger::net_Spawn	(CSE_Abstract* DC) 
{
	m_entrance_time				= 0;
	CCF_Shape *l_pShape			= xr_new<CCF_Shape>(this);
	collidable.model			= l_pShape;
	
	CSE_Abstract				*l_tpAbstract = (CSE_Abstract*)(DC);
	CSE_ALifeLevelChanger		*l_tpALifeLevelChanger = smart_cast<CSE_ALifeLevelChanger*>(l_tpAbstract);
	R_ASSERT					(l_tpALifeLevelChanger);

	m_game_vertex_id			= l_tpALifeLevelChanger->m_tNextGraphID;
	m_level_vertex_id			= l_tpALifeLevelChanger->m_dwNextNodeID;
	m_position					= l_tpALifeLevelChanger->m_tNextPosition;
	m_angles					= l_tpALifeLevelChanger->m_tAngles;

	m_bSilentMode				= !!l_tpALifeLevelChanger->m_bSilentMode;
	if (ai().get_level_graph()) {
		//. this information should be computed in xrAI
		ai_location().level_vertex	(ai().level_graph().vertex(u32(-1),Position()));
		ai_location().game_vertex	(ai().cross_table().vertex(ai_location().level_vertex_id()).game_vertex_id());
	}

	feel_touch.clear			();
	
	for (u32 i=0; i < l_tpALifeLevelChanger->shapes.size(); ++i) {
		CSE_Shape::shape_def	&S = l_tpALifeLevelChanger->shapes[i];
		switch (S.type) {
			case 0 : {
				l_pShape->add_sphere(S.data.sphere);
				break;
			}
			case 1 : {
				l_pShape->add_box(S.data.box);
				break;
			}
		}
	}

	BOOL						bOk = inherited::net_Spawn(DC);
	if (bOk) {
		l_pShape->ComputeBounds	();
		Fvector					P;
		XFORM().transform_tiny	(P,CFORM()->getSphere().P);
		setEnabled				(TRUE);
	}
	g_lchangers.push_back		(this);
	return						(bOk);
}
Ejemplo n.º 11
0
void CRadioactiveZone::Affect(SZoneObjectInfo* O) 
{
	float one				= 0.1f;
	float tg				= Device.fTimeGlobal;

	if(!O->object || O->f_time_affected+one > Device.fTimeGlobal) 
		return;

	clamp					(O->f_time_affected, tg-(one*3), tg);

	Fvector					pos; 
	XFORM().transform_tiny	(pos,CFORM()->getSphere().P);

	Fvector dir				={0,0,0}; 
	float power				= Power(O->object->Position().distance_to(pos),nearest_shape_radius(O));

	float impulse			= 0.0f;
	if(power < EPS)			
	{
		O->f_time_affected	= tg;
		return;
	}
	
	float send_power		= power*one;

	while(O->f_time_affected+one < tg)
	{
		CreateHit	(	O->object->ID(),
						ID(),
						dir,
						send_power,
						BI_NONE,
						Fvector().set(0.0f,0.0f,0.0f),
						impulse,
						m_eHitTypeBlowout);
#ifdef DEBUG
//		if(bDebug)
/*		Msg			(	"Zone[%s]-hit->[%s] Power=%3.3f Frame=%d Time=%3.3f", 
						cName().c_str(), 
						O->object->cName().c_str(), 
						send_power, 
						Device.dwFrame, 
						tg);*/
///		Msg( "Zone hit ___   damage = %.4f    Frame=%d ", send_power, Device.dwFrame );
#endif
		O->f_time_affected += one;
	}//while
}
Ejemplo n.º 12
0
void CMosquitoBald::Affect(SZoneObjectInfo* O) 
{
	CPhysicsShellHolder *pGameObject = smart_cast<CPhysicsShellHolder*>(O->object);
	if(!pGameObject) return;

	if(O->zone_ignore) return;

	Fvector P; 
	XFORM().transform_tiny(P,CFORM()->getSphere().P);

#ifdef DEBUG
	char l_pow[255]; 
	sprintf_s(l_pow, "zone hit. %.1f", Power(pGameObject->Position().distance_to(P)));
	if(bDebug) Msg("%s %s",*pGameObject->cName(), l_pow);
#endif

	Fvector hit_dir; 
	hit_dir.set(::Random.randF(-.5f,.5f), 
		::Random.randF(.0f,1.f), 
		::Random.randF(-.5f,.5f)); 
	hit_dir.normalize();


	Fvector position_in_bone_space;

	VERIFY(!pGameObject->getDestroy());

	float dist = pGameObject->Position().distance_to(P) - pGameObject->Radius();
	float power = Power(dist>0.f?dist:0.f);
	float impulse = m_fHitImpulseScale*power*pGameObject->GetMass();

	//статистика по объекту
	O->total_damage += power;
	O->hit_num++;

	if(power > 0.01f) 
	{
		m_dwDeltaTime = 0;
		position_in_bone_space.set(0.f,0.f,0.f);

		CreateHit(pGameObject->ID(),ID(),hit_dir,power,0,position_in_bone_space,impulse,m_eHitTypeBlowout);

		PlayHitParticles(pGameObject);
	}
}
Ejemplo n.º 13
0
BOOL CTeamBaseZone::net_Spawn	(CSE_Abstract* DC) 
{
	CCF_Shape					*l_pShape = xr_new<CCF_Shape>(this);
	collidable.model			= l_pShape;

	CSE_Abstract				*l_tpAbstract = (CSE_Abstract*)(DC);
	CSE_ALifeTeamBaseZone		*l_tpALifeScriptZone = smart_cast<CSE_ALifeTeamBaseZone*>(l_tpAbstract);
	R_ASSERT					(l_tpALifeScriptZone);

	feel_touch.clear			();

	for (u32 i=0; i < l_tpALifeScriptZone->shapes.size(); ++i) {
		CSE_Shape::shape_def	&S = l_tpALifeScriptZone->shapes[i];
		switch (S.type) {
			case 0 : {
				l_pShape->add_sphere(S.data.sphere);
				break;
			}
			case 1 : {
				l_pShape->add_box(S.data.box);
				break;
			}
		}
	}

	m_Team = l_tpALifeScriptZone->m_team;

	BOOL						bOk = inherited::net_Spawn(DC);
	if (bOk) {
		l_pShape->ComputeBounds	();
		Fvector					P;
		XFORM().transform_tiny	(P,CFORM()->getSphere().P);
		setEnabled				(TRUE);
	}

	if (GameID() != GAME_SINGLE && !g_dedicated_server)
	{
		char BaseMapLocation[1024];
		sprintf_s (BaseMapLocation, "mp_team_base_%d_location", m_Team);
		(Level().MapManager().AddMapLocation(BaseMapLocation,ID()))->EnablePointer();
		
	};

	return						(bOk);
}
Ejemplo n.º 14
0
BOOL CCustomZone::feel_touch_contact(CObject* O) 
{
	if (smart_cast<CCustomZone*>(O))				return FALSE;
	if (smart_cast<CBreakableObject*>(O))			return FALSE;
	if (0==smart_cast<IKinematics*>(O->Visual()))	return FALSE;

	if (O->ID() == ID())
		return		(FALSE);

	CGameObject *object = smart_cast<CGameObject*>(O);
    if (!object || !object->IsVisibleForZones())
		return		(FALSE);

	if (!((CCF_Shape*)CFORM())->Contact(O))
		return		(FALSE);

	return			(object->feel_touch_on_contact(this));
}
Ejemplo n.º 15
0
void CMosquitoBald::UpdateSecondaryHit()
{
	if(m_dwAffectFrameNum == Device.dwFrame)	
		return;

	m_dwAffectFrameNum	= Device.dwFrame;
	if(Device.dwPrecacheFrame)					
		return;

	OBJECT_INFO_VEC_IT it;
	for(it = m_ObjectInfoMap.begin(); m_ObjectInfoMap.end() != it; ++it) 
	{
		if(!(*it).object->getDestroy())
		{
			CPhysicsShellHolder *pGameObject = smart_cast<CPhysicsShellHolder*>((&(*it))->object);
			if(!pGameObject) return;

			if((&(*it))->zone_ignore) return;
			Fvector P; 
			XFORM().transform_tiny(P,CFORM()->getSphere().P);

			Fvector hit_dir; 
			hit_dir.set(	::Random.randF(-.5f,.5f), 
							::Random.randF(.0f,1.f), 
							::Random.randF(-.5f,.5f)); 
			hit_dir.normalize();

			Fvector position_in_bone_space;

			VERIFY(!pGameObject->getDestroy());

			float dist = pGameObject->Position().distance_to(P) - pGameObject->Radius();
			float power = m_fSecondaryHitPower * RelativePower(dist>0.f?dist:0.f, Radius());
			if(power<0.0f)
				return;

			float impulse = m_fHitImpulseScale*power*pGameObject->GetMass();
			position_in_bone_space.set(0.f,0.f,0.f);
			CreateHit(pGameObject->ID(),ID(),hit_dir,power,0,position_in_bone_space,impulse,m_eHitTypeBlowout);
		}
	}
}
Ejemplo n.º 16
0
void CRadioactiveZone::UpdateWorkload					(u32	dt)
{
	if (IsEnabled() && GameID() != GAME_SINGLE)
	{	
		OBJECT_INFO_VEC_IT it;
		Fvector pos; 
		XFORM().transform_tiny(pos,CFORM()->getSphere().P);
		for(it = m_ObjectInfoMap.begin(); m_ObjectInfoMap.end() != it; ++it) 
		{
			if( !(*it).object->getDestroy() && (*it).object->CLS_ID == CLSID_OBJECT_ACTOR)
			{
				//=====================================
				NET_Packet	l_P;
				l_P.write_start();
				l_P.read_start();

				float dist = (*it).object->Position().distance_to(pos);
				float power = Power(dist)*dt/1000;
///				Msg("Zone Dist %f, Radiation Power %f, ", dist, power);

				SHit HS;
				HS.GenHeader(GE_HIT, (*it).object->ID());
				HS.whoID  =ID();
				HS.weaponID = ID();
				HS.dir = Fvector().set(0,0,0);
				HS.power = power;
				HS.boneID = BI_NONE;
				HS.p_in_bone_space = Fvector().set(0, 0, 0);
				HS.impulse = 0.0f;
				HS.hit_type = ALife::eHitTypeRadiation;
				
				HS.Write_Packet_Cont(l_P);

				(*it).object->OnEvent(l_P, HS.PACKET_TYPE);
				//=====================================
			};
		}
	}
	inherited::UpdateWorkload(dt);
}
Ejemplo n.º 17
0
void CRadioactiveZone::UpdateWorkload					(u32	dt)
{
	if (IsEnabled() && GameID() != eGameIDSingle)
	{	
		OBJECT_INFO_VEC_IT it;
		Fvector pos; 
		XFORM().transform_tiny(pos,CFORM()->getSphere().P);
		for(it = m_ObjectInfoMap.begin(); m_ObjectInfoMap.end() != it; ++it) 
		{
			if( !(*it).object->getDestroy() && smart_cast<CActor*>((*it).object))
			{
				//=====================================
				NET_Packet	l_P;
				l_P.write_start();
				l_P.read_start();

				float dist			= (*it).object->Position().distance_to(pos);
				float power			= Power(dist,nearest_shape_radius(it))*dt/1000;

				SHit				HS;
				HS.GenHeader		(GE_HIT, (*it).object->ID());
				HS.whoID			= ID();
				HS.weaponID			= ID();
				HS.dir				= Fvector().set(0,0,0);
				HS.power			= power;
				HS.boneID			= BI_NONE;
				HS.p_in_bone_space	= Fvector().set(0, 0, 0);
				HS.impulse			= 0.0f;
				HS.hit_type			= m_eHitTypeBlowout;
				
				HS.Write_Packet_Cont(l_P);

				(*it).object->OnEvent(l_P, HS.PACKET_TYPE);
				//=====================================
			};
		}
	}
	inherited::UpdateWorkload(dt);
}
Ejemplo n.º 18
0
float CLevelChanger::Radius		() const
{
	return CFORM()->getRadius	();
}
Ejemplo n.º 19
0
// called as usual
void CCustomZone::shedule_Update(u32 dt)
{
	m_zone_flags.set(eZoneIsActive, FALSE);

	if (IsEnabled())
	{
		const Fsphere& s		= CFORM()->getSphere();
		Fvector					P;
		XFORM().transform_tiny	(P,s.P);

		// update
		feel_touch_update		(P,s.R);

		//пройтись по всем объектам в зоне
		//и проверить их состояние
		for(OBJECT_INFO_VEC_IT it = m_ObjectInfoMap.begin(); 
			m_ObjectInfoMap.end() != it; ++it) 
		{
			CGameObject* pObject		= (*it).object;
			if (!pObject)				continue;
			CEntityAlive* pEntityAlive	= smart_cast<CEntityAlive*>(pObject);
			SZoneObjectInfo& info		= (*it);

			info.dw_time_in_zone += dt;

			if((!info.small_object && m_iDisableHitTime != -1 && (int)info.dw_time_in_zone > m_iDisableHitTime) ||
				(info.small_object && m_iDisableHitTimeSmall != -1 && (int)info.dw_time_in_zone > m_iDisableHitTimeSmall))
			{
				if(!pEntityAlive || !pEntityAlive->g_Alive())
					info.zone_ignore = true;
			}
			if(m_iDisableIdleTime != -1 && (int)info.dw_time_in_zone > m_iDisableIdleTime)
			{
				if(!pEntityAlive || !pEntityAlive->g_Alive())
					StopObjectIdleParticles( pObject );
			}

			//если есть хотя бы один не дисабленый объект, то
			//зона считается активной
			if(info.zone_ignore == false) 
				m_zone_flags.set(eZoneIsActive,TRUE);
		}

		if(eZoneStateIdle ==  m_eZoneState)
			CheckForAwaking();

		inherited::shedule_Update(dt);

		// check "fast-mode" border
		float	cam_distance	= Device.vCameraPosition.distance_to(P)-s.R;
		
		if (cam_distance>FASTMODE_DISTANCE && !m_zone_flags.test(eAlwaysFastmode) )	
			o_switch_2_slow	();
		else									
			o_switch_2_fast	();

		if (!m_zone_flags.test(eFastMode))
			UpdateWorkload	(dt);

	};

	UpdateOnOffState	();

	if( !IsGameTypeSingle() && Local() )
	{
		if(Device.dwTimeGlobal > m_ttl)
			DestroyObject ();
	}
}
Ejemplo n.º 20
0
BOOL CTeamBaseZone::feel_touch_contact	(CObject* O)
{
	CActor*	pActor = smart_cast<CActor*>(O);
	if (!pActor) return (FALSE);
	return ((CCF_Shape*)CFORM())->Contact(O);
}
Ejemplo n.º 21
0
void CLevelChanger::Center		(Fvector& C) const
{
	XFORM().transform_tiny		(C,CFORM()->getSphere().P);
}
Ejemplo n.º 22
0
void CCustomZone::CalcDistanceTo(const Fvector& P, float& dist, float& radius)
{
	R_ASSERT			(CFORM()->Type()==cftShape);
	CCF_Shape* Sh		= (CCF_Shape*)CFORM();

	dist				= P.distance_to(Position());
	float sr			= CFORM()->getSphere().R;
	//quick test
	if(Sh->Shapes().size()==1)
	{
		radius			= sr;
		return;
	}
/*
	//2nd quick test
	Fvector				SC;
	float				dist2;
	XF.transform_tiny	(SC,CFORM()->getSphere().P);
	dist2				= P.distance_to(SC);
	if(dist2>sr)
	{
		radius		= sr;
		return;
	}
*/
	//full test
	const Fmatrix& XF	= XFORM();
	xr_vector<CCF_Shape::shape_def>& Shapes = Sh->Shapes();
	CCF_Shape::shape_def* nearest_s = NULL;
	float nearest = flt_max;


	Fvector sP;

	xr_vector<CCF_Shape::shape_def>::iterator it = Shapes.begin();
	xr_vector<CCF_Shape::shape_def>::iterator it_e = Shapes.end();
	for(;it!=it_e;++it)
	{
		CCF_Shape::shape_def& s = *it;
		float d = 0.0f;
		switch (s.type)
		{
		case 0: // sphere
			sP = s.data.sphere.P;
			break;
		case 1: // box
			sP = s.data.box.c;
			break;
		}

		XF.transform_tiny(sP);
		d = P.distance_to(sP);
		if(d<nearest)
		{
			nearest		= d;
			nearest_s	= &s;
		}
	}
	R_ASSERT(nearest_s);
	
	dist	= nearest;

	if(nearest_s->type==0)
		radius	= nearest_s->data.sphere.R;
	else
	{
		float r1 = nearest_s->data.box.i.magnitude();
		float r2 = nearest_s->data.box.j.magnitude();
		float r3 = nearest_s->data.box.k.magnitude();
		radius = _max(r1,r2);
		radius = _max(radius,r3);
	}

}
Ejemplo n.º 23
0
float CTeamBaseZone::Radius			() const
{
	return						(CFORM()->getRadius());
}
Ejemplo n.º 24
0
void CTeamBaseZone::Center			(Fvector &C) const
{
	XFORM().transform_tiny	(C,CFORM()->getSphere().P);
}
Ejemplo n.º 25
0
BOOL CLevelChanger::feel_touch_contact	(CObject *object)
{
	return	(((CCF_Shape*)CFORM())->Contact(object)) && smart_cast<CActor*>(object);
}
Ejemplo n.º 26
0
BOOL CScriptZone::feel_touch_contact	(CObject* O)
{
    return						(((CCF_Shape*)CFORM())->Contact(O));
}