Пример #1
0
void MapSpecials::applyLineSlopeThing(SLADEMap* map, MapThing* thing)
{
	int lineid = thing->intProperty("arg0");
	if (!lineid)
	{
		LOG_MESSAGE(1, "Ignoring line slope thing %d with no lineid argument", thing->getIndex());
		return;
	}

	// These are computed on first use, to avoid extra work if no lines match
	MapSector* containing_sector = nullptr;
	double thingz;

	vector<MapLine*> lines;
	map->getLinesById(lineid, lines);
	for (unsigned b = 0; b < lines.size(); b++)
	{
		MapLine* line = lines[b];

		// Line slope things only affect the sector on the side of the line
		// that faces the thing
		double side = MathStuff::lineSide(thing->point(), line->seg());
		MapSector* target = nullptr;
		if (side < 0)
			target = line->backSector();
		else if (side > 0)
			target = line->frontSector();
		if (!target)
			continue;

		// Need to know the containing sector's height to find the thing's true height
		if (!containing_sector)
		{
			int containing_sector_idx = map->sectorAt(thing->point());
			if (containing_sector_idx < 0)
				return;
			containing_sector = map->getSector(containing_sector_idx);
			thingz = (
				containing_sector->getPlane<p>().height_at(thing->point())
				+ thing->floatProperty("height")
			);
		}

		// Three points: endpoints of the line, and the thing itself
		plane_t target_plane = target->getPlane<p>();
		fpoint3_t p1(lines[b]->x1(), lines[b]->y1(), target_plane.height_at(lines[b]->point1()));
		fpoint3_t p2(lines[b]->x2(), lines[b]->y2(), target_plane.height_at(lines[b]->point2()));
		fpoint3_t p3(thing->xPos(), thing->yPos(), thingz);
		target->setPlane<p>(MathStuff::planeFromTriangle(p1, p2, p3));
	}
}
Пример #2
0
/* MapSector::isWithin
 * Returns true if the point is inside the sector
 *******************************************************************/
bool MapSector::isWithin(fpoint2_t point)
{
	// Check with bbox first
	if (!boundingBox().contains(point))
		return false;

	// Find nearest line in the sector
	double dist;
	double min_dist = 999999;
	MapLine* nline = nullptr;
	for (unsigned a = 0; a < connected_sides.size(); a++)
	{
		// Calculate distance to line
		//if (connected_sides[a] == NULL) {
		//	LOG_MESSAGE(3, "Warning: connected side #%i is a NULL pointer!", a);
		//	continue;
		//} else if (connected_sides[a]->getParentLine() == NULL) {
		//	LOG_MESSAGE(3, "Warning: connected side #%i has a NULL pointer parent line!", connected_sides[a]->getIndex());
		//	continue;
		//}
		dist = connected_sides[a]->getParentLine()->distanceTo(point);

		// Check distance
		if (dist < min_dist)
		{
			nline = connected_sides[a]->getParentLine();
			min_dist = dist;
		}
	}

	// No nearest (shouldn't happen)
	if (!nline)
		return false;

	// Check the side of the nearest line
	double side = MathStuff::lineSide(point, nline->seg());
	if (side >= 0 && nline->frontSector() == this)
		return true;
	else if (side < 0 && nline->backSector() == this)
		return true;
	else
		return false;
}
Пример #3
0
/* MapSpecials::processEternitySlopes
* Process Eternity slope specials
*******************************************************************/
void MapSpecials::processEternitySlopes(SLADEMap* map)
{
	// Eternity plans on having a few slope mechanisms,
	// which must be evaluated in a specific order.
	//  - Plane_Align, in line order
	//  - vertex triangle slopes, in sector order (wip)
	//  - Plane_Copy, in line order

	// First things first: reset every sector to flat planes
	for(unsigned a = 0; a < map->nSectors(); a++)
	{
		MapSector* target = map->getSector(a);
		target->setPlane<FLOOR_PLANE>(plane_t::flat(target->getPlaneHeight<FLOOR_PLANE>()));
		target->setPlane<CEILING_PLANE>(plane_t::flat(target->getPlaneHeight<CEILING_PLANE>()));
	}

	// Plane_Align (line special 181)
	for(unsigned a = 0; a < map->nLines(); a++)
	{
		MapLine* line = map->getLine(a);
		if(line->getSpecial() != 181)
			continue;

		MapSector* sector1 = line->frontSector();
		MapSector* sector2 = line->backSector();
		if(!sector1 || !sector2)
		{
			LOG_MESSAGE(1, "Ignoring Plane_Align on one-sided line %d", line->getIndex());
			continue;
		}
		if(sector1 == sector2)
		{
			LOG_MESSAGE(1, "Ignoring Plane_Align on line %d, which has the same sector on both sides", line->getIndex());
			continue;
		}

		int floor_arg = line->intProperty("arg0");
		if(floor_arg == 1)
			applyPlaneAlign<FLOOR_PLANE>(line, sector1, sector2);
		else if(floor_arg == 2)
			applyPlaneAlign<FLOOR_PLANE>(line, sector2, sector1);

		int ceiling_arg = line->intProperty("arg1");
		if(ceiling_arg == 1)
			applyPlaneAlign<CEILING_PLANE>(line, sector1, sector2);
		else if(ceiling_arg == 2)
			applyPlaneAlign<CEILING_PLANE>(line, sector2, sector1);
	}

	// Plane_Copy
	vector<MapSector*> sectors;
	for(unsigned a = 0; a < map->nLines(); a++)
	{
		MapLine* line = map->getLine(a);
		if(line->getSpecial() != 118)
			continue;

		int tag;
		MapSector* front = line->frontSector();
		MapSector* back = line->backSector();
		if((tag = line->intProperty("arg0")))
		{
			sectors.clear();
			map->getSectorsByTag(tag, sectors);
			if(sectors.size())
				front->setFloorPlane(sectors[0]->getFloorPlane());
		}
		if((tag = line->intProperty("arg1")))
		{
			sectors.clear();
			map->getSectorsByTag(tag, sectors);
			if(sectors.size())
				front->setCeilingPlane(sectors[0]->getCeilingPlane());
		}
		if((tag = line->intProperty("arg2")))
		{
			sectors.clear();
			map->getSectorsByTag(tag, sectors);
			if(sectors.size())
				back->setFloorPlane(sectors[0]->getFloorPlane());
		}
		if((tag = line->intProperty("arg3")))
		{
			sectors.clear();
			map->getSectorsByTag(tag, sectors);
			if(sectors.size())
				back->setCeilingPlane(sectors[0]->getCeilingPlane());
		}

		// The fifth "share" argument copies from one side of the line to the
		// other
		if(front && back)
		{
			int share = line->intProperty("arg4");

			if((share & 3) == 1)
				back->setFloorPlane(front->getFloorPlane());
			else if((share & 3) == 2)
				front->setFloorPlane(back->getFloorPlane());

			if((share & 12) == 4)
				back->setCeilingPlane(front->getCeilingPlane());
			else if((share & 12) == 8)
				front->setCeilingPlane(back->getCeilingPlane());
		}
	}
}
Пример #4
0
/* MapSpecials::processZDoomSlopes
 * Process ZDoom slope specials
 *******************************************************************/
void MapSpecials::processZDoomSlopes(SLADEMap* map)
{
	// ZDoom has a variety of slope mechanisms, which must be evaluated in a
	// specific order.
	//  - Plane_Align, in line order
	//  - line slope + sector tilt + vavoom, in thing order
	//  - slope copy things, in thing order
	//  - overwrite vertex heights with vertex height things
	//  - vertex triangle slopes, in sector order
	//  - Plane_Copy, in line order

	// First things first: reset every sector to flat planes
	for (unsigned a = 0; a < map->nSectors(); a++)
	{
		MapSector* target = map->getSector(a);
		target->setPlane<FLOOR_PLANE>(plane_t::flat(target->getPlaneHeight<FLOOR_PLANE>()));
		target->setPlane<CEILING_PLANE>(plane_t::flat(target->getPlaneHeight<CEILING_PLANE>()));
	}

	// Plane_Align (line special 181)
	for (unsigned a = 0; a < map->nLines(); a++)
	{
		MapLine* line = map->getLine(a);
		if (line->getSpecial() != 181)
			continue;

		MapSector* sector1 = line->frontSector();
		MapSector* sector2 = line->backSector();
		if (!sector1 || !sector2)
		{
			LOG_MESSAGE(1, "Ignoring Plane_Align on one-sided line %d", line->getIndex());
			continue;
		}
		if (sector1 == sector2)
		{
			LOG_MESSAGE(1, "Ignoring Plane_Align on line %d, which has the same sector on both sides", line->getIndex());
			continue;
		}

		int floor_arg = line->intProperty("arg0");
		if (floor_arg == 1)
			applyPlaneAlign<FLOOR_PLANE>(line, sector1, sector2);
		else if (floor_arg == 2)
			applyPlaneAlign<FLOOR_PLANE>(line, sector2, sector1);

		int ceiling_arg = line->intProperty("arg1");
		if (ceiling_arg == 1)
			applyPlaneAlign<CEILING_PLANE>(line, sector1, sector2);
		else if (ceiling_arg == 2)
			applyPlaneAlign<CEILING_PLANE>(line, sector2, sector1);
	}

	// Line slope things (9500/9501), sector tilt things (9502/9503), and
	// vavoom things (1500/1501), all in the same pass
	for (unsigned a = 0; a < map->nThings(); a++)
	{
		MapThing* thing = map->getThing(a);

		// Line slope things
		if (thing->getType() == 9500)
			applyLineSlopeThing<FLOOR_PLANE>(map, thing);
		else if (thing->getType() == 9501)
			applyLineSlopeThing<CEILING_PLANE>(map, thing);
		// Sector tilt things
		else if (thing->getType() == 9502)
			applySectorTiltThing<FLOOR_PLANE>(map, thing);
		else if (thing->getType() == 9503)
			applySectorTiltThing<CEILING_PLANE>(map, thing);
		// Vavoom things
		else if (thing->getType() == 1500)
			applyVavoomSlopeThing<FLOOR_PLANE>(map, thing);
		else if (thing->getType() == 1501)
			applyVavoomSlopeThing<CEILING_PLANE>(map, thing);
	}

	// Slope copy things (9510/9511)
	for (unsigned a = 0; a < map->nThings(); a++)
	{
		MapThing* thing = map->getThing(a);

		if (thing->getType() == 9510 || thing->getType() == 9511)
		{
			int target_idx = map->sectorAt(thing->point());
			if (target_idx < 0)
				continue;
			MapSector* target = map->getSector(target_idx);

			// First argument is the tag of a sector whose slope should be copied
			int tag = thing->intProperty("arg0");
			if (!tag)
			{
				LOG_MESSAGE(1, "Ignoring slope copy thing in sector %d with no argument", target_idx);
				continue;
			}

			vector<MapSector*> tagged_sectors;
			map->getSectorsByTag(tag, tagged_sectors);
			if (tagged_sectors.empty())
			{
				LOG_MESSAGE(1, "Ignoring slope copy thing in sector %d; no sectors have target tag %d", target_idx, tag);
				continue;
			}

			if (thing->getType() == 9510)
				target->setFloorPlane(tagged_sectors[0]->getFloorPlane());
			else
				target->setCeilingPlane(tagged_sectors[0]->getCeilingPlane());
		}
	}

	// Vertex height things
	// These only affect the calculation of slopes and shouldn't be stored in
	// the map data proper, so instead of actually changing vertex properties,
	// we store them in a hashmap.
	VertexHeightMap vertex_floor_heights;
	VertexHeightMap vertex_ceiling_heights;
	for (unsigned a = 0; a < map->nThings(); a++)
	{
		MapThing* thing = map->getThing(a);
		if (thing->getType() == 1504 || thing->getType() == 1505)
		{
			// TODO there could be more than one vertex at this point
			MapVertex* vertex = map->vertexAt(thing->xPos(), thing->yPos());
			if (vertex)
			{
				if (thing->getType() == 1504)
					vertex_floor_heights[vertex] = thing->floatProperty("height");
				else if (thing->getType() == 1505)
					vertex_ceiling_heights[vertex] = thing->floatProperty("height");
			}
		}
	}

	// Vertex heights -- only applies for sectors with exactly three vertices.
	// Heights may be set by UDMF properties, or by a vertex height thing
	// placed exactly on the vertex (which takes priority over the prop).
	vector<MapVertex*> vertices;
	for (unsigned a = 0; a < map->nSectors(); a++)
	{
		MapSector* target = map->getSector(a);
		vertices.clear();
		target->getVertices(vertices);
		if (vertices.size() != 3)
			continue;

		applyVertexHeightSlope<FLOOR_PLANE>(target, vertices, vertex_floor_heights);
		applyVertexHeightSlope<CEILING_PLANE>(target, vertices, vertex_ceiling_heights);
	}

	// Plane_Copy
	vector<MapSector*> sectors;
	for (unsigned a = 0; a < map->nLines(); a++)
	{
		MapLine* line = map->getLine(a);
		if (line->getSpecial() != 118)
			continue;

		int tag;
		MapSector* front = line->frontSector();
		MapSector* back = line->backSector();
		if ((tag = line->intProperty("arg0")) && front)
		{
			sectors.clear();
			map->getSectorsByTag(tag, sectors);
			if (sectors.size())
				front->setFloorPlane(sectors[0]->getFloorPlane());
		}
		if ((tag = line->intProperty("arg1")) && front)
		{
			sectors.clear();
			map->getSectorsByTag(tag, sectors);
			if (sectors.size())
				front->setCeilingPlane(sectors[0]->getCeilingPlane());
		}
		if ((tag = line->intProperty("arg2")) && back)
		{
			sectors.clear();
			map->getSectorsByTag(tag, sectors);
			if (sectors.size())
				back->setFloorPlane(sectors[0]->getFloorPlane());
		}
		if ((tag = line->intProperty("arg3")) && back)
		{
			sectors.clear();
			map->getSectorsByTag(tag, sectors);
			if (sectors.size())
				back->setCeilingPlane(sectors[0]->getCeilingPlane());
		}

		// The fifth "share" argument copies from one side of the line to the
		// other
		if (front && back)
		{
			int share = line->intProperty("arg4");

			if ((share & 3) == 1)
				back->setFloorPlane(front->getFloorPlane());
			else if ((share & 3) == 2)
				front->setFloorPlane(back->getFloorPlane());

			if ((share & 12) == 4)
				back->setCeilingPlane(front->getCeilingPlane());
			else if ((share & 12) == 8)
				front->setCeilingPlane(back->getCeilingPlane());
		}
	}
}