Esempio n. 1
0
	void Update(float aStep)
	{
		// was used?
		bool wasUsed = false;

		// get team affiliation
		unsigned int aHitTeam = Database::team.Get(mHitId);

		if (Database::pickuplink.Find(mId))
			Database::Deactivate(mHitId);

		// for each pickup link...
#ifdef PICKUP_CASCADE_LINK_CHAIN
		const Database::Typed<Link *> &links = Database::link.Get(mHitId);
#endif
		for (Database::Typed<LinkTemplate>::Iterator itor(Database::pickuplink.Get(mId).Find(aHitTeam)); itor.IsValid(); ++itor)
		{
			// if the recipient supports the link...
			if (Database::linktemplate.Get(mHitId).Find(itor.GetKey()))
			{
				// open link templates for the hit entity
				Database::Typed<LinkTemplate> &linktemplates = Database::linktemplate.Open(mHitId);

#ifdef PICKUP_CASCADE_LINK_CHAIN
				// cascade along link chain
				bool chain = true;
				for (unsigned int name = itor.GetKey(); name != 0; name = linktemplates.Get(name).mNext)
				{
					// get the link template
					LinkTemplate &linktemplate = linktemplates.Open(name);

					// save previous contents
					unsigned int prev = linktemplate.mSecondary;

					// get the link group
					unsigned int group = linktemplate.mGroup;
					bool groupempty = true;

					// get the corresponding link
					if (Link *link = links.Get(name))
					{
						// if the link is empty...
						if (!Database::entity.Find(link->GetSecondary()))
						{
							// clear value
							prev = 0U;
						}
					}

					// for each link...
					for (Database::Typed<Link *>::Iterator itor2(&links); itor2.IsValid(); ++itor2)
					{
						// if the link is not empty...
						Link *link = itor2.GetValue();
						if (Database::entity.Find(link->GetSecondary()))
						{
							// group is not empty
							if (groupempty && linktemplates.Get(itor2.GetKey()).mGroup == group)
							{
								groupempty = false;
							}
						}
					}

					// set link template based on chaining
					linktemplate.mSecondary = chain ? link : prev;
					DebugPrint("%s link %08x: %s -> %s\n", Database::name.Get(mHitId).c_str(), name, Database::name.Get(prev).c_str(), Database::name.Get(link).c_str());

					// if the group is empty
					if (groupempty)
					{
						// stop chaining
						chain = false;
					}
					else
					{
						// push link template contents forward
						link = prev;
					}

					// close link template
					linktemplates.Close(name);
				}
#else
				// link name
				unsigned int name = itor.GetKey();

				// get baseline version
				unsigned int parent = Database::parent.Get(mHitId);
				const LinkTemplate &linktemplatebase = Database::linktemplate.Get(parent).Get(name);

				// merge templates (HACK)
				// TO DO: figure out how to determine template overrides
				const LinkTemplate &link = itor.GetValue();
				LinkTemplate merge(linktemplatebase);
				merge.mSecondary = link.mSecondary;
				merge.mOffset = link.mOffset * linktemplatebase.mOffset;

				// set link template based on link
				DebugPrint("%s link %08x: %s -> %s\n", Database::name.Get(mHitId).c_str(), name, Database::name.Get(linktemplates.Get(name).mSecondary).c_str(), Database::name.Get(link.mSecondary).c_str());
				linktemplates.Put(name, merge);
#endif

#ifdef PICKUP_CASCADE_LINK_CHAIN
				// close link templates
				Database::linktemplate.Close(mHitId);
#endif

				// was used
				wasUsed = true;
			}
		}

		// for each pickup resource...
		for (Database::Typed<float>::Iterator itor(Database::pickupresource.Get(mId).Find(aHitTeam)); itor.IsValid(); ++itor)
		{
			// if the recipient supports the resource...
			if (Resource *resource = Database::resource.Get(mHitId).Get(itor.GetKey()))
			{
				// amount to add
				const float add = itor.GetValue();

				// get the resource template
				const ResourceTemplate &resourcetemplate = Database::resourcetemplate.Get(mHitId).Get(itor.GetKey());

				// if not at the limit...
				if ((add > 0.0f && resource->GetValue() < resourcetemplate.mMaximum) ||
					(add < 0.0f && resource->GetValue() > 0.0f))
				{
					// add the resource
					resource->Add(mId, add);

					// was used
					wasUsed = true;
				}
			}
		}

		if (Database::pickuplink.Find(mId))
			Database::Activate(mHitId);

		if (Pickup *pickup = Database::pickup.Get(mId))
			pickup->Kill(mTime);

		// get hit owner
		unsigned int aOwnerId = Database::owner.Get(mHitId);

		if (!wasUsed)
		{
			// notify all source kill listeners
			Database::killsignal.Get(mHitId)(mHitId, mId);

			// notify all owner kill listeners
			Database::killsignal.Get(aOwnerId)(aOwnerId, mId);

			// notify all death listeners
			Database::deathsignal.Get(mId)(mId, mHitId);
		}

		Deactivate();
		delete this;
	}