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); }
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); }
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); }