⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aas_map.c

📁 quakeIII源码这个不用我多说吧
💻 C
📖 第 1 页 / 共 2 页
字号:
			Error ("MAX_MAPFILE_BRUSHSIDES");
		side = brush->original_sides + n;

		newside = newbrush->original_sides + n;
		newside->original = NULL;
		newside->winding = NULL;
		newside->contents = side->contents;
		newside->flags = side->flags;
		newside->surf = side->surf;
		newside->planenum = side->planenum;
		newside->texinfo = side->texinfo;
		nummapbrushsides++;
	} //end for
	//
	nummapbrushes++;
	mapent->numbrushes++;
	return newbrush;
} //end of the function AAS_CopyMapBrush
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
int mark_entities[MAX_MAP_ENTITIES];

int AAS_AlwaysTriggered_r(char *targetname)
{
	int i;

	if (!strlen(targetname)) {
		return false;
	}
	//
	for (i = 0; i < num_entities; i++) {
		// if the entity will activate the given targetname
		if ( !strcmp(targetname, ValueForKey(&entities[i], "target")) ) {
			// if this activator is present in deathmatch
			if (!(atoi(ValueForKey(&entities[i], "spawnflags")) & SPAWNFLAG_NOT_DEATHMATCH)) {
				// if it is a trigger_always entity
				if (!strcmp("trigger_always", ValueForKey(&entities[i], "classname"))) {
					return true;
				}
				// check for possible trigger_always entities activating this entity
				if ( mark_entities[i] ) {
					Warning( "entity %d, classname %s has recursive targetname %s\n", i,
										ValueForKey(&entities[i], "classname"), targetname );
					return false;
				}
				mark_entities[i] = true;
				if ( AAS_AlwaysTriggered_r(ValueForKey(&entities[i], "targetname")) ) {
					return true;
				}
			}
		}
	}
	return false;
}

int AAS_AlwaysTriggered(char *targetname) {
	memset( mark_entities, 0, sizeof(mark_entities) );
	return AAS_AlwaysTriggered_r( targetname );
}
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
int AAS_ValidEntity(entity_t *mapent)
{
	int i;
	char target[1024];

	//all world brushes are used for AAS
	if (mapent == &entities[0])
	{
		return true;
	} //end if
	//some of the func_wall brushes are also used for AAS
	else if (!strcmp("func_wall", ValueForKey(mapent, "classname")))
	{
		//Log_Print("found func_wall entity %d\n", mapent - entities);
		//if the func wall is used in deathmatch
		if (!(atoi(ValueForKey(mapent, "spawnflags")) & SPAWNFLAG_NOT_DEATHMATCH))
		{
			//Log_Print("func_wall USED in deathmatch mode %d\n", atoi(ValueForKey(mapent, "spawnflags")));
			return true;
		} //end if
	} //end else if
	else if (!strcmp("func_door_rotating", ValueForKey(mapent, "classname")))
	{
		//if the func_door_rotating is present in deathmatch
		if (!(atoi(ValueForKey(mapent, "spawnflags")) & SPAWNFLAG_NOT_DEATHMATCH))
		{
			//if the func_door_rotating is always activated in deathmatch
			if (AAS_AlwaysTriggered(ValueForKey(mapent, "targetname")))
			{
				//Log_Print("found func_door_rotating in deathmatch\ntargetname %s\n", ValueForKey(mapent, "targetname"));
				return true;
			} //end if
		} //end if
	} //end else if
	else if (!strcmp("trigger_hurt", ValueForKey(mapent, "classname")))
	{
		//"dmg" is the damage, for instance: "dmg" "666"
		return true;
	} //end else if
	else if (!strcmp("trigger_push", ValueForKey(mapent, "classname")))
	{
		return true;
	} //end else if
	else if (!strcmp("trigger_multiple", ValueForKey(mapent, "classname")))
	{
		//find out if the trigger_multiple is pointing to a target_teleporter
		strcpy(target, ValueForKey(mapent, "target"));
		for (i = 0; i < num_entities; i++)
		{
			//if the entity will activate the given targetname
			if (!strcmp(target, ValueForKey(&entities[i], "targetname")))
			{
				if (!strcmp("target_teleporter", ValueForKey(&entities[i], "classname")))
				{
					return true;
				} //end if
			} //end if
		} //end for
	} //end else if
	else if (!strcmp("trigger_teleport", ValueForKey(mapent, "classname")))
	{
		return true;
	} //end else if
	else if (!strcmp("func_static", ValueForKey(mapent, "classname")))
	{
		//FIXME: easy/medium/hard/deathmatch specific?
		return true;
	} //end else if
	else if (!strcmp("func_door", ValueForKey(mapent, "classname")))
	{
		return true;
	} //end else if
	return false;
} //end of the function AAS_ValidEntity
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
int AAS_TransformPlane(int planenum, vec3_t origin, vec3_t angles)
{
	float newdist, matrix[3][3];
	vec3_t normal;

	//rotate the node plane
	VectorCopy(mapplanes[planenum].normal, normal);
	CreateRotationMatrix(angles, matrix);
	RotatePoint(normal, matrix);
	newdist = mapplanes[planenum].dist + DotProduct(normal, origin);
	return FindFloatPlane(normal, newdist);
} //end of the function AAS_TransformPlane
//===========================================================================
// this function sets the func_rotating_door in it's final position
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_PositionFuncRotatingBrush(entity_t *mapent, mapbrush_t *brush)
{
	int spawnflags, i;
	float distance;
	vec3_t movedir, angles, pos1, pos2;
	side_t *s;

	spawnflags = FloatForKey(mapent, "spawnflags");
	VectorClear(movedir);
	if (spawnflags & DOOR_X_AXIS)
		movedir[2] = 1.0;		//roll
	else if (spawnflags & DOOR_Y_AXIS)
		movedir[0] = 1.0;		//pitch
	else // Z_AXIS
		movedir[1] = 1.0;		//yaw

	// check for reverse rotation
	if (spawnflags & DOOR_REVERSE)
		VectorInverse(movedir);

	distance = FloatForKey(mapent, "distance");
	if (!distance) distance = 90;

	GetVectorForKey(mapent, "angles", angles);
	VectorCopy(angles, pos1);
	VectorMA(angles, -distance, movedir, pos2);
	// if it starts open, switch the positions
	if (spawnflags & DOOR_START_OPEN)
	{
		VectorCopy(pos2, angles);
		VectorCopy(pos1, pos2);
		VectorCopy(angles, pos1);
		VectorInverse(movedir);
	} //end if
	//
	for (i = 0; i < brush->numsides; i++)
	{
		s = &brush->original_sides[i];
		s->planenum = AAS_TransformPlane(s->planenum, mapent->origin, pos2);
	} //end for
	//
	FreeBrushWindings(brush);
	AAS_MakeBrushWindings(brush);
	AddBrushBevels(brush);
	FreeBrushWindings(brush);
} //end of the function AAS_PositionFuncRotatingBrush
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_PositionBrush(entity_t *mapent, mapbrush_t *brush)
{
	side_t *s;
	float newdist;
	int i, notteam;
	char *model;

	if (!strcmp(ValueForKey(mapent, "classname"), "func_door_rotating"))
	{
		AAS_PositionFuncRotatingBrush(mapent, brush);
	} //end if
	else
	{
		if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
		{
			for (i = 0; i < brush->numsides; i++)
			{
				s = &brush->original_sides[i];
				newdist = mapplanes[s->planenum].dist +
						DotProduct(mapplanes[s->planenum].normal, mapent->origin);
				s->planenum = FindFloatPlane(mapplanes[s->planenum].normal, newdist);
			} //end for
		} //end if
		//if it's a trigger hurt
		if (!strcmp("trigger_hurt", ValueForKey(mapent, "classname")))
		{
			notteam = FloatForKey(mapent, "bot_notteam");
			if ( notteam == 1 ) {
				brush->contents |= CONTENTS_NOTTEAM1;
			}
			else if ( notteam == 2 ) {
				brush->contents |= CONTENTS_NOTTEAM2;
			}
			else {
				// always avoid so set lava contents
				brush->contents |= CONTENTS_LAVA;
			}
		} //end if
		//
		else if (!strcmp("trigger_push", ValueForKey(mapent, "classname")))
		{
			//set the jumppad contents
			brush->contents = CONTENTS_JUMPPAD;
			//Log_Print("found trigger_push brush\n");
		} //end if
		//
		else if (!strcmp("trigger_multiple", ValueForKey(mapent, "classname")))
		{
			//set teleporter contents
			brush->contents = CONTENTS_TELEPORTER;
			//Log_Print("found trigger_multiple teleporter brush\n");
		} //end if
		//
		else if (!strcmp("trigger_teleport", ValueForKey(mapent, "classname")))
		{
			//set teleporter contents
			brush->contents = CONTENTS_TELEPORTER;
			//Log_Print("found trigger_teleport teleporter brush\n");
		} //end if
		else if (!strcmp("func_door", ValueForKey(mapent, "classname")))
		{
			//set mover contents
			brush->contents = CONTENTS_MOVER;
			//get the model number
			model = ValueForKey(mapent, "model");
			brush->modelnum = atoi(model+1);
		} //end if
	} //end else
} //end of the function AAS_PositionBrush
//===========================================================================
// uses the global cfg_t cfg
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_CreateMapBrushes(mapbrush_t *brush, entity_t *mapent, int addbevels)
{
	int i;
	//side_t *s;
	mapbrush_t *bboxbrushes[16];

	//if the brushes are not from an entity used for AAS
	if (!AAS_ValidEntity(mapent))
	{
		nummapbrushsides -= brush->numsides;
		brush->numsides = 0;
		return;
	} //end if
	//
	AAS_PositionBrush(mapent, brush);
	//from all normal solid brushes only the textured brush sides will
	//be used as bsp splitters, so set the right texinfo reference here
	AAS_SetTexinfo(brush);
	//remove contents detail flag, otherwise player clip contents won't be
	//bsped correctly for AAS!
	brush->contents &= ~CONTENTS_DETAIL;
	//if the brush has contents area portal it should be the only contents
	if (brush->contents & (CONTENTS_AREAPORTAL|CONTENTS_CLUSTERPORTAL))
	{
		brush->contents = CONTENTS_CLUSTERPORTAL;
		brush->leafnum = -1;
	} //end if
	//window and playerclip are used for player clipping, make them solid
	if (brush->contents & (CONTENTS_WINDOW | CONTENTS_PLAYERCLIP))
	{
		//
		brush->contents &= ~(CONTENTS_WINDOW | CONTENTS_PLAYERCLIP);
		brush->contents |= CONTENTS_SOLID;
		brush->leafnum = -1;
	} //end if
	//
	if (brush->contents & CONTENTS_BOTCLIP)
	{
		brush->contents = CONTENTS_SOLID;
		brush->leafnum = -1;
	} //end if
	//
	//Log_Write("brush %d contents = ", brush->brushnum);
	//PrintContents(brush->contents);
	//Log_Write("\r\n");
	//if not one of the following brushes then the brush is NOT used for AAS
	if (!(brush->contents & (CONTENTS_SOLID
									| CONTENTS_LADDER
									| CONTENTS_CLUSTERPORTAL
									| CONTENTS_DONOTENTER
									| CONTENTS_TELEPORTER
									| CONTENTS_JUMPPAD
									| CONTENTS_WATER
									| CONTENTS_LAVA
									| CONTENTS_SLIME
									| CONTENTS_MOVER
									)))
	{
		nummapbrushsides -= brush->numsides;
		brush->numsides = 0;
		return;
	} //end if
	//fix the map brush
	//AAS_FixMapBrush(brush);
	//if brush bevels should be added (for real map brushes, not bsp map brushes)
	if (addbevels)
	{
		//NOTE: we first have to get the mins and maxs of the brush before
		//			creating the brush bevels... the mins and maxs are used to
		//			create them. so we call MakeBrushWindings to get the mins
		//			and maxs and then after creating the bevels we free the
		//			windings because they are created for all sides (including
		//			bevels) a little later
		AAS_MakeBrushWindings(brush);
		AddBrushBevels(brush);
		FreeBrushWindings(brush);
	} //end if
	//NOTE: add the brush to the WORLD entity!!!
	mapent = &entities[0];
	//there's at least one new brush for now
	nummapbrushes++;
	mapent->numbrushes++;
	//liquid brushes are expanded for the maximum possible bounding box
	if (brush->contents & (CONTENTS_WATER
									| CONTENTS_LAVA
									| CONTENTS_SLIME 
									| CONTENTS_TELEPORTER
									| CONTENTS_JUMPPAD
									| CONTENTS_DONOTENTER
									| CONTENTS_MOVER
									))
	{
		brush->expansionbbox = 0;
		//NOTE: the first bounding box is the max
		//FIXME: use max bounding box created from all bboxes
		AAS_ExpandMapBrush(brush, cfg.bboxes[0].mins, cfg.bboxes[0].maxs);
		AAS_MakeBrushWindings(brush);
	} //end if
	//area portal brushes are NOT expanded
	else if (brush->contents & CONTENTS_CLUSTERPORTAL)
	{
		brush->expansionbbox = 0;
		//NOTE: the first bounding box is the max
		//FIXME: use max bounding box created from all bboxes
		AAS_ExpandMapBrush(brush, cfg.bboxes[0].mins, cfg.bboxes[0].maxs);
		AAS_MakeBrushWindings(brush);
	} //end if
	//all solid brushes are expanded for all bounding boxes
	else if (brush->contents & (CONTENTS_SOLID
										| CONTENTS_LADDER
										))
	{
		//brush for the first bounding box
		bboxbrushes[0] = brush;
		//make a copy for the other bounding boxes
		for (i = 1; i < cfg.numbboxes; i++)
		{
			bboxbrushes[i] = AAS_CopyMapBrush(brush, mapent);
		} //end for
		//expand every brush for it's bounding box and create windings
		for (i = 0; i < cfg.numbboxes; i++)
		{
			AAS_ExpandMapBrush(bboxbrushes[i], cfg.bboxes[i].mins, cfg.bboxes[i].maxs);
			bboxbrushes[i]->expansionbbox = cfg.bboxes[i].presencetype;
			AAS_MakeBrushWindings(bboxbrushes[i]);
		} //end for
	} //end else
} //end of the function AAS_CreateMapBrushes

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -