Esempio n. 1
0
bool NextPathElement( std::string& out, size_t& pos, size_t& length, const std::string& path )
{
	if(pos >= (path.length()-1))
		return false;
	
	size_t next = path.find_first_of(DirSeperators, pos);
	if(next == std::string::npos)
		next = path.length();
	
	length = next-pos;
	out = path.substr(pos, length);
	pos = next+1;
	
	if(!length)
		return NextPathElement(out, pos, length, path);
	return true;
}
Esempio n. 2
0
/**
**  Unit moves! Generic function called from other actions.
**
**  @param unit  Pointer to unit.
**
**  @return      >0 remaining path length, 0 wait for path, -1
**               reached goal, -2 can't reach the goal.
*/
int DoActionMove(CUnit &unit)
{
	Vec2i posd; // movement in tile.
	int d;

	Assert(unit.CanMove());

	if (!unit.Moving && (unit.Type->Animations->Move != unit.Anim.CurrAnim || !unit.Anim.Wait)) {
		Assert(!unit.Anim.Unbreakable);

		// FIXME: So units flying up and down are not affected.
		unit.IX = 0;
		unit.IY = 0;

		UnmarkUnitFieldFlags(unit);
		d = NextPathElement(unit, &posd.x, &posd.y);
		MarkUnitFieldFlags(unit);
		switch (d) {
			case PF_UNREACHABLE: // Can't reach, stop
				if (unit.Player->AiEnabled) {
					AiCanNotMove(unit);
				}
				unit.Moving = 0;
				return d;
			case PF_REACHED: // Reached goal, stop
				unit.Moving = 0;
				return d;
			case PF_WAIT: // No path, wait
				// Reset frame to still frame while we wait
				// FIXME: Unit doesn't animate.
				unit.Frame = unit.Type->StillFrame;
				UnitUpdateHeading(unit);
				unit.Wait = 10;

				unit.Moving = 0;
				return d;
			default: // On the way moving
				unit.Moving = 1;
				break;
		}

		if (unit.Type->UnitType == UnitTypeNaval) { // Boat (un)docking?
			const CMapField &mf_cur = *Map.Field(unit.Offset);
			const CMapField &mf_next = *Map.Field(unit.tilePos + posd);

			if (mf_cur.WaterOnMap() && mf_next.CoastOnMap()) {
				PlayUnitSound(unit, VoiceDocking);
			} else if (mf_cur.CoastOnMap() && mf_next.WaterOnMap()) {
				PlayUnitSound(unit, VoiceDocking); // undocking
			}
		}
		Vec2i pos = unit.tilePos + posd;
		unit.MoveToXY(pos);

		// Remove unit from the current selection
		if (unit.Selected && !Map.Field(pos)->playerInfo.IsTeamVisible(*ThisPlayer)) {
			if (NumSelected == 1) { //  Remove building cursor
				CancelBuildingMode();
			}
			if (!ReplayRevealMap) {
				UnSelectUnit(unit);
				SelectionChanged();
			}
		}

		unit.IX = -posd.x * PixelTileSize.x;
		unit.IY = -posd.y * PixelTileSize.y;
		unit.Frame = unit.Type->StillFrame;
		UnitHeadingFromDeltaXY(unit, posd);
	} else {
		posd.x = Heading2X[unit.Direction / NextDirection];
		posd.y = Heading2Y[unit.Direction / NextDirection];
		d = unit.pathFinderData->output.Length + 1;
	}

	unit.pathFinderData->output.Cycles++;//reset have to be manualy controled by caller.
	int move = UnitShowAnimationScaled(unit, unit.Type->Animations->Move, Map.Field(unit.Offset)->Cost);

	unit.IX += posd.x * move;
	unit.IY += posd.y * move;

	// Finished move animation, set Moving to 0 so we recalculate the path
	// next frame
	// FIXME: this is broken for subtile movement
	if (!unit.Anim.Unbreakable && !unit.IX && !unit.IY) {
		unit.Moving = 0;
	}
	return d;
}
Esempio n. 3
0
void Path::canonicalize( Path& out, int type ) const
{
	// "./Foo/./Bar/../Xyz"
	// "foo/bar/../.."
	// "/home/foo/bar"
	
	// On a relative path the working directory is appened at the front.
	// "." elements will be removed.
	// On ".." elements the previous element will be removed.
	// Path separators will be changed to fit the system.
	
	std::vector<std::string> entries;
	entries.reserve(10); // TODO: Maybe declare this as a constant. <.<

	if((type == Path::Absolute) && !isAbsolutePath())
		out = CurDir();
	
	out /= *this;

	size_t pos = 0;
	size_t length = 0;
	std::string entry;
	while(NextPathElement(entry, pos, length, out.m_Path))
	{
		if(entry == ".")
		{
			continue;
		}
		else if(entry == "..")
		{
			if(!entries.empty())
			{
				entries.pop_back(); // easy peasy ;)
				continue;
			}
			else if(type != Path::Relative)
			{
// 				Expect(false, "Can't process path entry '..'! (path: '%s')", out.m_Path.c_str());
			}
		}
		
		entries.push_back( entry );
	}
	
	switch(type)
	{
		case Path::Absolute:
			// ...
			break;
		case Path::Relative:
		{
			if(entries.empty())
				out.m_Path = ".";
			else
				out.m_Path = "";
		} break;
		
		default:
			FatalError("Invalid path type: %u", type);
	}
	
	for(int i = 0; i < entries.size(); i++)
	{
		out.m_Path += entries[i];
		if(i < entries.size()-1) // not last element?
			out.m_Path.push_back(DirSeperator); // Could fail if you process something like this: '/..', see security test below.
	}
	
// 	if(type != Path::Relative)
// 		Expect(out.isAbsolutePath(), "Processing path '%s' did not yield a valid result. (result: '%s')", m_Path.c_str(), out.m_Path.c_str());
}