void CmpProjectileWeaponUsable::use()
{
	if(m_timeTillCanFire == 0)
	{
		// Determine the character which is firing the projectile (the owner of the weapon).
		ICmpOwnable_CPtr cmpOwnable = m_objectManager->get_component(m_objectID, cmpOwnable);
		ObjectID firer = cmpOwnable->owner();
		if(!firer.valid()) throw Exception("Can't use a projectile weapon when it's not owned");

		// Check that there's enough ammo.
		ICmpInventory_Ptr cmpFirerInventory = m_objectManager->get_component(firer, cmpFirerInventory);
		if(!cmpFirerInventory) throw Exception("The firer must have an inventory component");
		if(cmpFirerInventory->consumables_count(m_ammoType) > 0)
		{
			// Fire a bullet from each hotspot of the weapon (note that this in principle makes it easy to implement things like double-barrelled shotguns).
			const std::vector<std::string>& spots = hotspots();
			for(size_t i=0, size=spots.size(); i<size; ++i)
			{
				boost::optional<Vector3d> pos = hotspot_position(spots[i]);
				boost::optional<Vector3d> ori = hotspot_orientation(spots[i]);
				if(pos && ori)
				{
					ObjectSpecification specification = m_objectManager->get_archetype(m_ammoType);
					specification.set_component_property("Projectile", "Firer", firer);
					specification.set_component_property("Simulation", "Position", *pos);
					specification.set_component_property("Simulation", "Velocity", m_muzzleSpeed * *ori);
					m_objectManager->queue_for_construction(specification);
				}
			}

			cmpFirerInventory->destroy_consumables(m_ammoType, 1);
			m_timeTillCanFire = m_firingInterval;
		}
	}
}
Esempio n. 2
0
//#################### PUBLIC METHODS ####################
void CmdUseActiveItem::execute(const ObjectManager_Ptr& objectManager, const std::vector<CollisionPolygon_Ptr>& polygons, const OnionTree_CPtr& tree,
							   const NavManager_CPtr& navManager, int milliseconds)
{
	ICmpInventory_Ptr cmpInventory = objectManager->get_component(m_objectID, cmpInventory);	if(!cmpInventory) return;
	ObjectID activeItem = cmpInventory->active_item();											if(!activeItem.valid()) return;
	ICmpUsable_Ptr cmpItemUsable = objectManager->get_component(activeItem, cmpItemUsable);		if(!cmpItemUsable) return;
	cmpItemUsable->use();
}
Esempio n. 3
0
//#################### CONSTRUCTORS ####################
CmpInventory::CmpInventory(const ObjectID& activeItem, const std::map<std::string,int>& consumables, const std::set<ObjectID>& items)
:	m_initialised(false), m_activeItem(activeItem), m_consumables(consumables), m_items(items)
{
	// Note:	We can't update the usable groups at this stage, because the items we're holding generally haven't been created yet.
	//			Instead, they are initialised "on demand" later on.

	// Check that the active item (if any) is actually one of the items in the inventory.
	if(activeItem.valid() && items.find(activeItem) == items.end())
	{
		throw Exception("The active item must be in the inventory");
	}
}
void CmpCharacterModelRender::render_first_person() const
{
	ICmpInventory_Ptr cmpInventory = m_objectManager->get_component(m_objectID, cmpInventory);
	assert(cmpInventory);

	ObjectID activeItem = cmpInventory->active_item();
	if(!activeItem.valid()) return;

	ICmpBasicModelRender_Ptr cmpItemRender = m_objectManager->get_component(activeItem, cmpItemRender);
	if(!cmpItemRender) return;

	cmpItemRender->render_first_person();
	render_crosshair();
}
void CmpCharacterModelRender::render() const
{
	ICmpOrientation_CPtr cmpOrientation = m_objectManager->get_component(m_objectID, cmpOrientation);
	ICmpPosition_CPtr cmpPosition = m_objectManager->get_component(m_objectID, cmpPosition);

	const Vector3d& p = cmpPosition->position();
	const Vector3d& n = cmpOrientation->nuv_axes()->n();
	const Vector3d& u = cmpOrientation->nuv_axes()->u();
	const Vector3d& v = cmpOrientation->nuv_axes()->v();

	if(m_modelPose != NULL)
	{
		RBTMatrix_CPtr mat = construct_model_matrix(p, n, u, v);
		glPushMatrix();
			glMultMatrixd(&mat->rep()[0]);

			// Render the model.
			model()->render(m_modelPose);

			// Render the active item (if any).
			ICmpInventory_Ptr cmpInventory = m_objectManager->get_component(m_objectID, cmpInventory);	assert(cmpInventory);
			ObjectID activeItem = cmpInventory->active_item();
			if(activeItem.valid())
			{
				ICmpBasicModelRender_Ptr cmpItemRender = m_objectManager->get_component(activeItem, cmpItemRender);
				if(cmpItemRender)
				{
					cmpItemRender->render_child();
				}
			}
		glPopMatrix();
	}

	if(m_highlights)
	{
		// If the object should be highlighted, render the object's bounds.
		render_bounds(p);
	}

	// Render the object's NUV axes.
	render_nuv_axes(p, n, u, v);
}
void CmpCharacterModelRender::update_animation(int milliseconds)
{
	// Decide which animation should be playing, and update it.
	ICmpAnimChooser_Ptr cmpAnimChooser = m_objectManager->get_component(m_objectID, cmpAnimChooser);	assert(cmpAnimChooser);
	m_animController->request_animation(cmpAnimChooser->choose_animation());
	m_animController->update(milliseconds);

	// Clear any existing pose modifiers.
	m_animController->clear_pose_modifiers();

	// Determine the animation extension of any carried item in order to determine which bones need to be inclined.
	std::string animExtension = "";		// the explicit initialisation is to make it clear that "" is the default

	ICmpInventory_Ptr cmpInventory = m_objectManager->get_component(m_objectID, cmpInventory);	assert(cmpInventory);
	ObjectID activeItem = cmpInventory->active_item();
	if(activeItem.valid())
	{
		ICmpOwnable_Ptr cmpItemOwnable = m_objectManager->get_component(activeItem, cmpItemOwnable);	assert(cmpItemOwnable);
		animExtension = cmpItemOwnable->anim_extension();
	}

	// Calculate the inclination of the object's coordinate system and apply pose modifiers to the relevant bones.
	BoneModifierMap::const_iterator it = m_inclineBones.find(animExtension);
	if(it != m_inclineBones.end())
	{
		ICmpOrientation_Ptr cmpOrientation = m_objectManager->get_component(m_objectID, cmpOrientation);
		const Vector3d& n = cmpOrientation->nuv_axes()->n();

		double sinInclination = n.z / n.length();
		if(sinInclination < -1) sinInclination = -1;
		if(sinInclination > 1) sinInclination = 1;
		double inclination = asin(sinInclination);

		for(std::map<std::string,Vector3d>::const_iterator jt=it->second.begin(), jend=it->second.end(); jt!=jend; ++jt)
		{
			m_animController->set_pose_modifier(jt->first, PoseModifier(jt->second, -inclination));
		}
	}

	// Configure the pose.
	m_modelPose = model()->configure_pose(m_animController);

	// Update the animation for the active item (if any), e.g. the weapon being carried.
	if(activeItem.valid())
	{
		ICmpOrientation_CPtr cmpOrientation = m_objectManager->get_component(m_objectID, cmpOrientation);
		ICmpPosition_CPtr cmpPosition = m_objectManager->get_component(m_objectID, cmpPosition);

		const Vector3d& p = cmpPosition->position();
		const Vector3d& n = cmpOrientation->nuv_axes()->n();
		const Vector3d& u = cmpOrientation->nuv_axes()->u();
		const Vector3d& v = cmpOrientation->nuv_axes()->v();

		RBTMatrix_CPtr modelMatrix = construct_model_matrix(p, n, u, v);

		ICmpOwnable_Ptr cmpItemOwnable = m_objectManager->get_component(activeItem, cmpItemOwnable);	assert(cmpItemOwnable);
		ICmpBasicModelRender_Ptr cmpItemRender = m_objectManager->get_component(activeItem, cmpItemRender);
		if(cmpItemRender)
		{
			cmpItemRender->update_child_animation(milliseconds, skeleton()->bone_hierarchy(), cmpItemOwnable->attach_point(), modelMatrix);
		}
	}
}