void CALifeUpdateManager::teleport_object	(ALife::_OBJECT_ID id, GameGraph::_GRAPH_ID game_vertex_id, u32 level_vertex_id, const Fvector &position)
{
    CSE_ALifeDynamicObject					*object = objects().object(id,true);
    if (!object) {
        Msg									("! cannot teleport entity with id %d",id);
        return;
    }

#ifdef DEBUG
    if (psAI_Flags.test(aiALife)) {
        Msg									("[LSS] teleporting object [%s][%s][%d] from level [%s], position [%f][%f][%f] to level [%s], position [%f][%f][%f]",
                                             object->name_replace(),
                                             *object->s_name,
                                             object->ID,
                                             *(ai().game_graph().header().level(ai().game_graph().vertex(object->m_tGraphID)->level_id()).name()),
                                             VPUSH(ai().game_graph().vertex(object->m_tGraphID)->level_point()),
                                             *(ai().game_graph().header().level(ai().game_graph().vertex(game_vertex_id)->level_id()).name()),
                                             VPUSH(ai().game_graph().vertex(game_vertex_id)->level_point())
                    );
    }
#endif

    if (object->m_bOnline)
        switch_offline						(object);
    graph().change							(object,object->m_tGraphID,game_vertex_id);
    object->m_tNodeID						= level_vertex_id;
    object->o_Position						= position;
    CSE_ALifeMonsterAbstract				*monster_abstract = smart_cast<CSE_ALifeMonsterAbstract*>(object);
    if (monster_abstract)
        monster_abstract->m_tNextGraphID	= object->m_tGraphID;
}
bool CSE_ALifeGroupAbstract::synchronize_location	()
{
	if (m_tpMembers.empty())
		return					(true);

	CSE_ALifeDynamicObject		*object = smart_cast<CSE_ALifeDynamicObject*>(base());
	VERIFY						(object);
	
	ALife::OBJECT_VECTOR::iterator	I = m_tpMembers.begin();
	ALife::OBJECT_VECTOR::iterator	E = m_tpMembers.end();
	for ( ; I != E; ++I)
		ai().alife().objects().object(*I)->synchronize_location	();

	CSE_ALifeDynamicObject		&member = *ai().alife().objects().object(*I);
	object->o_Position			= member.o_Position;
	object->m_tNodeID			= member.m_tNodeID;

	if (object->m_tGraphID != member.m_tGraphID) {
		if (!object->m_bOnline)
			object->alife().graph().change	(object,object->m_tGraphID,member.m_tGraphID);
		else
			object->m_tGraphID	= member.m_tGraphID;
	}

	object->m_fDistance			= member.m_fDistance;
	return						(true);
}
void CSE_ALifeGroupAbstract::switch_online	()
{
	CSE_ALifeDynamicObject		*object = smart_cast<CSE_ALifeDynamicObject*>(this);
	VERIFY						(object);

	R_ASSERT					(!object->m_bOnline);
	object->m_bOnline			= true;

	ALife::OBJECT_IT			I = m_tpMembers.begin(), B = I;
	ALife::OBJECT_IT			E = m_tpMembers.end();
	u32							N = (u32)(E - I);
	for ( ; I != E; ++I) {
		CSE_ALifeDynamicObject	*J = ai().alife().objects().object(*I);
		if (m_bCreateSpawnPositions) {
			J->o_Position		= object->o_Position;
			J->m_tNodeID		= object->m_tNodeID;
			CSE_ALifeMonsterAbstract	*l_tpALifeMonsterAbstract = smart_cast<CSE_ALifeMonsterAbstract*>(J);
			if (l_tpALifeMonsterAbstract)
				l_tpALifeMonsterAbstract->o_torso.yaw = angle_normalize_signed((I - B)/N*PI_MUL_2);
		}
		object->alife().add_online	(J, false);
	}
	m_bCreateSpawnPositions		= false;
	object->alife().scheduled().remove	(object);
	object->alife().graph().remove		(object,object->m_tGraphID,false);
}
Beispiel #4
0
void CALifeSimulatorBase::register_object	(CSE_ALifeDynamicObject *object, bool add_object)
{
	object->on_before_register			();

	if (add_object)
		objects().add					(object);
	
	graph().update						(object);
	scheduled().add						(object);
	story_objects().add					(object->m_story_id,object);
	smart_terrains().add				(object);
	groups().add						(object);

	setup_simulator						(object);
	
	CSE_ALifeInventoryItem				*item = smart_cast<CSE_ALifeInventoryItem*>(object);
	if (item && item->attached()) {
		CSE_ALifeDynamicObject			*II = objects().object(item->base()->ID_Parent);

#ifdef DEBUG
		if (std::find(II->children.begin(),II->children.end(),item->base()->ID) != II->children.end()) {
			Msg							("[LSS] Specified item [%s][%d] is already attached to the specified object [%s][%d]",item->base()->name_replace(),item->base()->ID,II->name_replace(),II->ID);
			FATAL						("[LSS] Cannot recover from the previous error!");
		}
#endif

		II->children.push_back			(item->base()->ID);
		II->attach						(item,true,false);
	}

	if (can_register_objects())
		object->on_register				();
}
void CSE_ALifeGroupAbstract::try_switch_online		()
{
	CSE_ALifeDynamicObject						*I = smart_cast<CSE_ALifeDynamicObject*>(base());
	VERIFY										(I);
	
	// checking if the object is not an empty group of objects
	if (m_tpMembers.empty())
		return;

	I->try_switch_online				();
}
void CSE_InventoryBox::add_offline	(const xr_vector<ALife::_OBJECT_ID> &saved_children, const bool &update_registries)
{
	CSE_ALifeDynamicObjectVisual		*object = (this);

	for (u32 i=0, n=saved_children.size(); i<n; ++i) {
		CSE_ALifeDynamicObject	*child = smart_cast<CSE_ALifeDynamicObject*>(ai().alife().objects().object(saved_children[i],true));
		R_ASSERT				(child);
		child->m_bOnline		= false;

		CSE_ALifeInventoryItem	*inventory_item = smart_cast<CSE_ALifeInventoryItem*>(child);
		VERIFY2					(inventory_item,"Non inventory item object has parent?!");
#ifdef DEBUG
//		if (psAI_Flags.test(aiALife))
//			Msg					("[LSS] Destroying item [%s][%s][%d]",inventory_item->base()->name_replace(),*inventory_item->base()->s_name,inventory_item->base()->ID);
		Msg						(
			"[LSS][%d] Going offline [%d][%s][%d] with parent [%d][%s] on '%s'",
			Device.dwFrame,
			Device.dwTimeGlobal,
			inventory_item->base()->name_replace(),
			inventory_item->base()->ID,
			ID,
			name_replace(),
			"*SERVER*"
		);
#endif
		
		ALife::_OBJECT_ID				item_id = inventory_item->base()->ID;
		inventory_item->base()->ID		= object->alife().server().PerformIDgen(item_id);

		if (!child->can_save()) {
			object->alife().release		(child);
			--i;
			--n;
			continue;
		}

#ifdef DEBUG
		if (!client_data.empty())
			Msg							("CSE_InventoryBox::add_offline: client_data is cleared for [%d][%s]",ID,name_replace());
#endif // DEBUG
		if (!child->keep_saved_data_anyway())
			child->client_data.clear		();
		object->alife().graph().add		(child,child->m_tGraphID,false);
//		object->alife().graph().attach	(*object,inventory_item,child->m_tGraphID,true);
		alife().graph().remove			(child,child->m_tGraphID);
		children.push_back				(child->ID);
		child->ID_Parent				= ID;
	}


	CSE_ALifeDynamicObjectVisual::add_offline(saved_children, update_registries);
}
IC	void construct_string					(LPSTR result, u32 const result_size, const xr_vector<ALife::_OBJECT_ID> &restrictions)
{
	u32		count = xr_strlen(result) ? _GetItemCount(result) : 0;
	xr_vector<ALife::_OBJECT_ID>::const_iterator	I = restrictions.begin();
	xr_vector<ALife::_OBJECT_ID>::const_iterator	E = restrictions.end();
	for ( ; I != E; ++I) {
		CSE_ALifeDynamicObject	*object = ai().alife().objects().object(*I);
		if (ai().game_graph().vertex(object->m_tGraphID)->level_id() != ai().level_graph().level_id())
			continue;

		if (count)
			xr_strcat(result,result_size,",");
		xr_strcat(result,result_size,object->name_replace());
		++count;
	}
}
void CALifeUpdateManager::remove_restriction(ALife::_OBJECT_ID id, ALife::_OBJECT_ID restriction_id, const RestrictionSpace::ERestrictorTypes &restriction_type)
{
    CSE_ALifeDynamicObject					*object = objects().object(id,true);
    if (!object) {
        Msg									("! cannot remove restriction with id %d to the entity with id %d, because there is no creature with the specified id",restriction_id,id);
        return;
    }

    CSE_ALifeDynamicObject					*object_restrictor = objects().object(restriction_id,true);
    if (!object_restrictor) {
        Msg									("! cannot remove restriction with id %d to the entity with id %d, because there is no space restrictor with the specified id",restriction_id,id);
        return;
    }

    CSE_ALifeCreatureAbstract				*creature = smart_cast<CSE_ALifeCreatureAbstract*>(object);
    if (!creature) {
        Msg									("! cannot remove restriction with id %d to the entity with id %d, because there is an object with the specified id, but it is not a creature",restriction_id,id);
        return;
    }

    CSE_ALifeSpaceRestrictor				*restrictor = smart_cast<CSE_ALifeSpaceRestrictor*>(object_restrictor);
    if (!restrictor) {
        Msg									("! cannot remove restriction with id %d to the entity with id %d, because there is an object with the specified id, but it is not a space restrictor",restriction_id,id);
        return;
    }

    switch (restriction_type) {
    case RestrictionSpace::eRestrictorTypeOut : {
        xr_vector<ALife::_OBJECT_ID>::iterator	I = std::find(creature->m_dynamic_out_restrictions.begin(),creature->m_dynamic_out_restrictions.end(),restriction_id);
        if (I == creature->m_dynamic_out_restrictions.end()) {
            Msg							("~ cannot remove restriction with id [%d][%s] to the entity with id [%d][%s], because it is not added",restriction_id,object_restrictor->name_replace(),id,object->name_replace());
            return;
        }

        creature->m_dynamic_out_restrictions.erase(I);

        break;
    }
    case RestrictionSpace::eRestrictorTypeIn : {
        xr_vector<ALife::_OBJECT_ID>::iterator	I = std::find(creature->m_dynamic_in_restrictions.begin(),creature->m_dynamic_in_restrictions.end(),restriction_id);
        if (I == creature->m_dynamic_in_restrictions.end()) {
            Msg							("~ cannot remove restriction with id [%d][%s] to the entity with id [%d][%s], because it is not added",restriction_id,object_restrictor->name_replace(),id,object->name_replace());
            return;
        }

        creature->m_dynamic_in_restrictions.erase(I);

        break;
    }
    default :  {
        Msg								("! Invalid restriction type!");
        return;
    }
    }
}
void CSE_ALifeGroupAbstract::switch_offline	()
{
	CSE_ALifeDynamicObject		*object = smart_cast<CSE_ALifeDynamicObject*>(base());
	VERIFY						(object);

	R_ASSERT					(object->m_bOnline);
	object->m_bOnline			= false;

	ALife::OBJECT_IT			I = m_tpMembers.begin();
	ALife::OBJECT_IT			E = m_tpMembers.end();
	if (I != E) {
		CSE_ALifeMonsterAbstract		*tpGroupMember	= smart_cast<CSE_ALifeMonsterAbstract*>(ai().alife().objects().object(*I));
		CSE_ALifeMonsterAbstract		*tpGroup		= smart_cast<CSE_ALifeMonsterAbstract*>(this);
		if (tpGroupMember && tpGroup) {
			tpGroup->m_fCurSpeed		= tpGroup->m_fCurrentLevelGoingSpeed;
			tpGroup->o_Position			= tpGroupMember->o_Position;
			u32	dwNodeID				= tpGroup->m_tNodeID;
			tpGroup->m_tGraphID			= ai().cross_table().vertex(dwNodeID).game_vertex_id();
			tpGroup->m_fDistanceToPoint = ai().cross_table().vertex(dwNodeID).distance();
			tpGroup->m_tNextGraphID		= tpGroup->m_tGraphID;
			u16	wNeighbourCount			= ai().game_graph().vertex(tpGroup->m_tGraphID)->edge_count();
			CGameGraph::const_iterator	i,e;
			ai().game_graph().begin		(tpGroup->m_tGraphID,i,e);
			tpGroup->m_tPrevGraphID		= (*(i + object->randI(0,wNeighbourCount))).vertex_id();
		}
		object->alife().remove_online	(tpGroupMember,false);
		++I;
	}
	for ( ; I != E; ++I)
		object->alife().remove_online	(ai().alife().objects().object(*I),false);
	object->alife().scheduled().add		(object);
	object->alife().graph().add			(object,object->m_tGraphID,false);
}
Beispiel #10
0
CSE_Abstract *CALifeSimulatorBase::create(CSE_ALifeGroupAbstract *tpALifeGroupAbstract, CSE_ALifeDynamicObject *j)
{
	NET_Packet					tNetPacket;
	LPCSTR						S = pSettings->r_string(tpALifeGroupAbstract->base()->s_name,"monster_section");
	CSE_Abstract				*l_tpAbstract = F_entity_Create(S);
	R_ASSERT2					(l_tpAbstract,"Can't create entity.");
	CSE_ALifeDynamicObject		*k = smart_cast<CSE_ALifeDynamicObject*>(l_tpAbstract);
	R_ASSERT2					(k,"Non-ALife object in the 'game.spawn'");

	j->Spawn_Write				(tNetPacket,TRUE);
	k->Spawn_Read				(tNetPacket);
	tNetPacket.w_begin			(M_UPDATE);
	j->UPDATE_Write				(tNetPacket);
	u16							id;
	tNetPacket.r_begin			(id);
	k->UPDATE_Read				(tNetPacket);
	k->s_name					= S;
	k->m_tSpawnID				= j->m_tSpawnID;
	k->ID						= server().PerformIDgen(0xffff);
	k->m_bDirectControl			= false;
	k->m_bALifeControl			= true;
	
	string256					s_name_replace;
	strcpy_s						(s_name_replace,*k->s_name);
	if (k->ID < 1000)
		strcat					(s_name_replace,"0");
	if (k->ID < 100)
		strcat					(s_name_replace,"0");
	if (k->ID < 10)
		strcat					(s_name_replace,"0");
	string16					S1;
	strcat						(s_name_replace,itoa(k->ID,S1,10));
	k->set_name_replace			(s_name_replace);

	register_object				(k,true);
	k->spawn_supplies			();
	k->on_spawn					();
	return						(k);
}
void CSE_ALifeGroupAbstract::try_switch_offline		()
{
	// checking if group is not empty
	if (m_tpMembers.empty())
		return;

	// so, we have a group of objects
	// therefore check all the group members if they are ready to switch offline

	CSE_ALifeDynamicObject				*I = smart_cast<CSE_ALifeDynamicObject*>(base());
	VERIFY								(I);
	
	// iterating on group members
	u32 i = 0;
	u32 N = (u32)m_tpMembers.size();
	for (; i<N; ++i) {
		// casting group member to the abstract monster to get access to the Health property
		CSE_ALifeMonsterAbstract		*tpGroupMember = smart_cast<CSE_ALifeMonsterAbstract*>(ai().alife().objects().object(m_tpMembers[i]));
		if (!tpGroupMember)
			continue;
			
		// check if monster is not dead
		if (tpGroupMember->g_Alive()) {
			// so, monster is not dead
			// checking if the object is _not_ ready to switch offline
			if (!tpGroupMember->can_switch_offline())
				continue;
			
			if (!tpGroupMember->can_switch_online())
				// so, it is not ready, breaking a cycle, because we can't 
				// switch group offline since not all the group members are ready
				// to switch offline
				break;
			
			if (I->alife().graph().actor()->o_Position.distance_to(tpGroupMember->o_Position) <= I->alife().offline_distance())
				// so, it is not ready, breaking a cycle, because we can't 
				// switch group offline since not all the group members are ready
				// to switch offline
				break;

			continue;
		}

		// detach object from the group
		tpGroupMember->fHealth				= 0.f;
		tpGroupMember->m_bDirectControl		= true;
		m_tpMembers.erase					(m_tpMembers.begin() + i);
		tpGroupMember->m_bOnline			= false;
		CSE_ALifeInventoryItem				*item = smart_cast<CSE_ALifeInventoryItem*>(tpGroupMember);
		if (item && item->attached()) {
			CSE_ALifeDynamicObject			*object = ai().alife().objects().object(tpGroupMember->ID_Parent,true);
			if (object)
				object->detach				(item);
		}
		// store the __new separate object into the registries
		I->alife().register_object			(tpGroupMember);

		// and remove it from the graph point but do not remove it from the current level map
		CSE_ALifeInventoryItem				*l_tpALifeInventoryItem = smart_cast<CSE_ALifeInventoryItem*>(tpGroupMember);
		if (!l_tpALifeInventoryItem || !l_tpALifeInventoryItem->attached())
			I->alife().graph().remove		(tpGroupMember,tpGroupMember->m_tGraphID,false);

		tpGroupMember->m_bOnline			= true;
		--m_wCount;
		--i;
		--N;
	}

	// checking if group is not empty
	if (m_tpMembers.empty())
		return;

	if (!I->can_switch_offline())
		return;
	
	if (I->can_switch_online() || (i == N))
		I->alife().switch_offline			(I);
}
void CALifeUpdateManager::set_interactive		(ALife::_OBJECT_ID id, bool value)
{
    CSE_ALifeDynamicObject			*object = objects().object(id);
    VERIFY							(object);
    object->interactive				(value);
}
void CALifeUpdateManager::set_switch_offline	(ALife::_OBJECT_ID id, bool value)
{
    CSE_ALifeDynamicObject			*object = objects().object(id);
    VERIFY							(object);
    object->can_switch_offline		(value);
}