コード例 #1
0
ファイル: DeclAF.cpp プロジェクト: anonreclaimer/morpheus
/*
================
idDeclAF::ParseFixed
================
*/
bool idDeclAF::ParseFixed( idLexer &src ) {
	idToken token;
	idDeclAF_Constraint *constraint = new idDeclAF_Constraint;

	constraint->SetDefault( this );
	constraints.Alloc() = constraint;

	if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
			!src.ExpectTokenString( "{" ) ) {
		return false;
	}

	constraint->type = DECLAF_CONSTRAINT_FIXED;
	constraint->name = token;

	while( src.ReadToken( &token ) ) {

		if ( !token.Icmp( "body1" ) ) {
			src.ExpectTokenType( TT_STRING, 0, &token );
			constraint->body1 = token;
		} else if ( !token.Icmp( "body2" ) ) {
			src.ExpectTokenType( TT_STRING, 0, &token );
			constraint->body2 = token;
		} else if ( token == "}" ) {
			break;
		} else {
			src.Error( "unknown token %s in ball and socket joint", token.c_str() );
			return false;
		}
	}

	return true;
}
コード例 #2
0
ファイル: DeclAF.cpp プロジェクト: anonreclaimer/morpheus
/*
================
idDeclAF::ParseHinge
================
*/
bool idDeclAF::ParseHinge( idLexer &src ) {
	idToken token;
	idDeclAF_Constraint *constraint = new idDeclAF_Constraint;

	constraint->SetDefault( this );
	constraints.Alloc() = constraint;

	if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
			!src.ExpectTokenString( "{" ) ) {
		return false;
	}

	constraint->type = DECLAF_CONSTRAINT_HINGE;
	constraint->limit = idDeclAF_Constraint::LIMIT_NONE;
	constraint->name = token;
	constraint->friction = 0.5f;
	constraint->anchor.ToVec3().Zero();
	constraint->axis.ToVec3().Zero();

	while( src.ReadToken( &token ) ) {

		if ( !token.Icmp( "body1" ) ) {
			src.ExpectTokenType( TT_STRING, 0, &token );
			constraint->body1 = token;
		} else if ( !token.Icmp( "body2" ) ) {
			src.ExpectTokenType( TT_STRING, 0, &token );
			constraint->body2 = token;
		} else if ( !token.Icmp( "anchor" ) ) {
			if ( !constraint->anchor.Parse( src ) ) {
				return false;
			}
		} else if ( !token.Icmp( "axis" ) ) {
			if ( !constraint->axis.Parse( src ) ) {
				return false;
			}
		} else if ( !token.Icmp( "limit" ) ) {
			constraint->limitAngles[0] = src.ParseFloat();
			if ( !src.ExpectTokenString( "," ) ) {
				return false;
			}
			constraint->limitAngles[1] = src.ParseFloat();
			if ( !src.ExpectTokenString( "," ) ) {
				return false;
			}
			constraint->limitAngles[2] = src.ParseFloat();
			constraint->limit = idDeclAF_Constraint::LIMIT_CONE;
		} else if ( !token.Icmp( "friction" ) ) {
			constraint->friction = src.ParseFloat();
		} else if ( token == "}" ) {
			break;
		} else {
			src.Error( "unknown token %s in hinge", token.c_str() );
			return false;
		}
	}

	return true;
}
コード例 #3
0
ファイル: DeclAF.cpp プロジェクト: anonreclaimer/morpheus
/*
================
idDeclAF::ParseSpring
================
*/
bool idDeclAF::ParseSpring( idLexer &src ) {
	idToken token;
	idDeclAF_Constraint *constraint = new idDeclAF_Constraint;

	constraint->SetDefault( this );
	constraints.Alloc() = constraint;

	if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
			!src.ExpectTokenString( "{" ) ) {
		return false;
	}

	constraint->type = DECLAF_CONSTRAINT_SPRING;
	constraint->limit = idDeclAF_Constraint::LIMIT_NONE;
	constraint->name = token;
	constraint->friction = 0.5f;

	while( src.ReadToken( &token ) ) {

		if ( !token.Icmp( "body1" ) ) {
			src.ExpectTokenType( TT_STRING, 0, &token );
			constraint->body1 = token;
		} else if ( !token.Icmp( "body2" ) ) {
			src.ExpectTokenType( TT_STRING, 0, &token );
			constraint->body2 = token;
		} else if ( !token.Icmp( "anchor1" ) ) {
			if ( !constraint->anchor.Parse( src ) ) {
				return false;
			}
		} else if ( !token.Icmp( "anchor2" ) ) {
			if ( !constraint->anchor2.Parse( src ) ) {
				return false;
			}
		} else if ( !token.Icmp( "friction" ) ) {
			constraint->friction = src.ParseFloat();
		} else if ( !token.Icmp( "stretch" ) ) {
			constraint->stretch = src.ParseFloat();
		} else if ( !token.Icmp( "compress" ) ) {
			constraint->compress = src.ParseFloat();
		} else if ( !token.Icmp( "damping" ) ) {
			constraint->damping = src.ParseFloat();
		} else if ( !token.Icmp( "restLength" ) ) {
			constraint->restLength = src.ParseFloat();
		} else if ( !token.Icmp( "minLength" ) ) {
			constraint->minLength = src.ParseFloat();
		} else if ( !token.Icmp( "maxLength" ) ) {
			constraint->maxLength = src.ParseFloat();
		} else if ( token == "}" ) {
			break;
		} else {
			src.Error( "unknown token %s in spring", token.c_str() );
			return false;
		}
	}

	return true;
}
コード例 #4
0
ファイル: DeclAF.cpp プロジェクト: dcahrakos/RBDOOM-3-BFG
/*
================
idDeclAF::ParseSlider
================
*/
bool idDeclAF::ParseSlider( idLexer& src )
{
	idToken token;
	idDeclAF_Constraint* constraint = new( TAG_DECL ) idDeclAF_Constraint;
	
	constraint->SetDefault( this );
	constraints.Alloc() = constraint;
	
	if( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
			!src.ExpectTokenString( "{" ) )
	{
		return false;
	}
	
	constraint->type = DECLAF_CONSTRAINT_SLIDER;
	constraint->limit = idDeclAF_Constraint::LIMIT_NONE;
	constraint->name = token;
	constraint->friction = 0.5f;
	
	while( src.ReadToken( &token ) )
	{
	
		if( !token.Icmp( "body1" ) )
		{
			src.ExpectTokenType( TT_STRING, 0, &token );
			constraint->body1 = token;
		}
		else if( !token.Icmp( "body2" ) )
		{
			src.ExpectTokenType( TT_STRING, 0, &token );
			constraint->body2 = token;
		}
		else if( !token.Icmp( "axis" ) )
		{
			if( !constraint->axis.Parse( src ) )
			{
				return false;
			}
		}
		else if( !token.Icmp( "friction" ) )
		{
			constraint->friction = src.ParseFloat();
		}
		else if( token == "}" )
		{
			break;
		}
		else
		{
			src.Error( "unknown token %s in slider", token.c_str() );
			return false;
		}
	}
	
	return true;
}
コード例 #5
0
/*
================
idTypeInfoTools::VerifyVariable
================
*/
void idTypeInfoTools::VerifyVariable( const char *varName, const char *varType, const char *scope, const char *prefix, const char *postfix, const char *value, const void *varPtr, int varSize ) {
	idToken token;

	if ( typeError ) {
		return;
	}

	src->SkipUntilString( "=" );
	src->ExpectTokenType( TT_STRING, 0, &token );
	if ( token.Cmp( value ) != 0 ) {

		// NOTE: skip several things

		if ( IsRenderHandleVariable( varName, varType, scope, prefix, postfix, value ) ) {
			return;
		}

		if ( IsAllowedToChangedFromSaveGames( varName, varType, scope, prefix, postfix, value ) ) {
			return;
		}

		src->Warning( "state diff for %s%s::%s%s\n%s\n%s", prefix, scope, varName, postfix, token.c_str(), value );
		typeError = true;
	}
}
コード例 #6
0
ファイル: AASFile.cpp プロジェクト: MSylvia/iod3
/*
================
Reachability_Special_Read
================
*/
bool Reachability_Special_Read( idLexer &src, idReachability_Special *reach ) {
	idToken key, value;

	src.ExpectTokenString( "{" );
	while( src.ReadToken( &key ) ) {
		if ( key == "}" ) {
			return true;
		}
		src.ExpectTokenType( TT_STRING, 0, &value );
		reach->dict.Set( key, value );
	}
	return false;
}
コード例 #7
0
ファイル: DeclAF.cpp プロジェクト: anonreclaimer/morpheus
/*
================
idDeclAF::ParseBody
================
*/
bool idDeclAF::ParseBody( idLexer &src ) {
	bool hasJoint = false;
	idToken token;
	idAFVector angles;
	idDeclAF_Body *body = new idDeclAF_Body;

	bodies.Alloc() = body;

	body->SetDefault( this );

	if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
			!src.ExpectTokenString( "{" ) ) {
		return false;
	}

	body->name = token;
	if ( !body->name.Icmp( "origin" ) || !body->name.Icmp( "world" ) ) {
		src.Error( "a body may not be named \"origin\" or \"world\"" );
		return false;
	}

	while( src.ReadToken( &token ) ) {

		if ( !token.Icmp( "model" ) ) {
			if ( !src.ExpectTokenType( TT_NAME, 0, &token ) ) {
				return false;
			}
			if ( !token.Icmp( "box" ) ) {
				body->modelType = TRM_BOX;
				if ( !src.ExpectTokenString( "(" ) ||
					!body->v1.Parse( src ) ||
					!src.ExpectTokenString( "," ) ||
					!body->v2.Parse( src ) ||
					!src.ExpectTokenString( ")" ) ) {
					return false;
				}
			} else if ( !token.Icmp( "octahedron" ) ) {
				body->modelType = TRM_OCTAHEDRON;
				if ( !src.ExpectTokenString( "(" ) ||
					!body->v1.Parse( src ) ||
					!src.ExpectTokenString( "," ) ||
					!body->v2.Parse( src ) ||
					!src.ExpectTokenString( ")" ) ) {
					return false;
				}
			} else if ( !token.Icmp( "dodecahedron" ) ) {
				body->modelType = TRM_DODECAHEDRON;
				if ( !src.ExpectTokenString( "(" ) ||
					!body->v1.Parse( src ) ||
					!src.ExpectTokenString( "," ) ||
					!body->v2.Parse( src ) ||
					!src.ExpectTokenString( ")" ) ) {
					return false;
				}
			} else if ( !token.Icmp( "cylinder" ) ) {
				body->modelType = TRM_CYLINDER;
				if ( !src.ExpectTokenString( "(" ) ||
					!body->v1.Parse( src ) ||
					!src.ExpectTokenString( "," ) ||
					!body->v2.Parse( src ) ||
					!src.ExpectTokenString( "," ) ) {
					return false;
				}
				body->numSides = src.ParseInt();
				if ( !src.ExpectTokenString( ")" ) ) {
					return false;
				}
			} else if ( !token.Icmp( "cone" ) ) {
				body->modelType = TRM_CONE;
				if ( !src.ExpectTokenString( "(" ) ||
					!body->v1.Parse( src ) ||
					!src.ExpectTokenString( "," ) ||
					!body->v2.Parse( src ) ||
					!src.ExpectTokenString( "," ) ) {
					return false;
				}
				body->numSides = src.ParseInt();
				if ( !src.ExpectTokenString( ")" ) ) {
					return false;
				}
			} else if ( !token.Icmp( "bone" ) ) {
				body->modelType = TRM_BONE;
				if ( !src.ExpectTokenString( "(" ) ||
					!body->v1.Parse( src ) ||
					!src.ExpectTokenString( "," ) ||
					!body->v2.Parse( src ) ||
					!src.ExpectTokenString( "," ) ) {
					return false;
				}
				body->width = src.ParseFloat();
				if ( !src.ExpectTokenString( ")" ) ) {
					return false;
				}
			} else if ( !token.Icmp( "custom" ) ) {
				src.Error( "custom models not yet implemented" );
				return false;
			} else {
				src.Error( "unkown model type %s", token.c_str() );
				return false;
			}
		} else if ( !token.Icmp( "origin" ) ) {
			if ( !body->origin.Parse( src ) ) {
				return false;
			}
		} else if ( !token.Icmp( "angles" ) ) {
			if ( !angles.Parse( src ) ) {
				return false;
			}
			body->angles = idAngles( angles.ToVec3().x, angles.ToVec3().y, angles.ToVec3().z );
		} else if ( !token.Icmp( "joint" ) ) {
			if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
				return false;
			}
			body->jointName = token;
			hasJoint = true;
		} else if ( !token.Icmp( "mod" ) ) {
			if ( !src.ExpectAnyToken( &token ) ) {
				return false;
			}
			body->jointMod = JointModFromString( token.c_str() );
		} else if ( !token.Icmp( "density" ) ) {
			body->density = src.ParseFloat();
		} else if ( !token.Icmp( "inertiaScale" ) ) {
			src.Parse1DMatrix( 9, body->inertiaScale[0].ToFloatPtr() );
		} else if ( !token.Icmp( "friction" ) ) {
			body->linearFriction = src.ParseFloat();
			src.ExpectTokenString( "," );
			body->angularFriction = src.ParseFloat();
			src.ExpectTokenString( "," );
			body->contactFriction = src.ParseFloat();
		} else if ( !token.Icmp( "contents" ) ) {
			ParseContents( src, body->contents );
		} else if ( !token.Icmp( "clipMask" ) ) {
			ParseContents( src, body->clipMask );
		} else if ( !token.Icmp( "selfCollision" ) ) {
			body->selfCollision = src.ParseBool();
		} else if ( !token.Icmp( "containedjoints" ) ) {
			if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
				return false;
			}
			body->containedJoints = token;
		} else if ( !token.Icmp( "frictionDirection" ) ) {
			if ( !body->frictionDirection.Parse( src ) ) {
				return false;
			}
		} else if ( !token.Icmp( "contactMotorDirection" ) ) {
			if ( !body->contactMotorDirection.Parse( src ) ) {
				return false;
			}
		} else if ( token == "}" ) {
			break;
		} else {
			src.Error( "unknown token %s in body", token.c_str() );
			return false;
		}
	}

	if ( body->modelType == TRM_INVALID ) {
		src.Error( "no model set for body" );
		return false;
	}

	if ( !hasJoint ) {
		src.Error( "no joint set for body" );
		return false;
	}

	body->clipMask |= CONTENTS_MOVEABLECLIP;

	return true;
}
コード例 #8
0
ファイル: DeclAF.cpp プロジェクト: anonreclaimer/morpheus
/*
================
idDeclAF::ParseSettings
================
*/
bool idDeclAF::ParseSettings( idLexer &src ) {
	idToken token;

	if ( !src.ExpectTokenString( "{" ) ) {
		return false;
	}

	while( src.ReadToken( &token ) ) {

		if ( !token.Icmp( "mesh" ) ) {
			if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
				return false;
			}
		} else if ( !token.Icmp( "anim" ) ) {
			if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
				return false;
			}
		} else if ( !token.Icmp( "model" ) ) {
			if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
				return false;
			}
			model = token;
		} else if ( !token.Icmp( "skin" ) ) {
			if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ) {
				return false;
			}
			skin = token;
		} else if ( !token.Icmp( "friction" ) ) {

			defaultLinearFriction = src.ParseFloat();
			if ( !src.ExpectTokenString( "," ) ) {
				return false;
			}
			defaultAngularFriction = src.ParseFloat();
			if ( !src.ExpectTokenString( "," ) ) {
				return false;
			}
			defaultContactFriction = src.ParseFloat();
			if ( src.CheckTokenString( "," ) ) {
				defaultConstraintFriction = src.ParseFloat();
			}
		} else if ( !token.Icmp( "totalMass" ) ) {
			totalMass = src.ParseFloat();
		} else if ( !token.Icmp( "suspendSpeed" ) ) {

			suspendVelocity[0] = src.ParseFloat();
			if ( !src.ExpectTokenString( "," ) ) {
				return false;
			}
			suspendVelocity[1] = src.ParseFloat();
			if ( !src.ExpectTokenString( "," ) ) {
				return false;
			}
			suspendAcceleration[0] = src.ParseFloat();
			if ( !src.ExpectTokenString( "," ) ) {
				return false;
			}
			suspendAcceleration[1] = src.ParseFloat();
		} else if ( !token.Icmp( "noMoveTime" ) ) {
			noMoveTime = src.ParseFloat();
		} else if ( !token.Icmp( "noMoveTranslation" ) ) {
			noMoveTranslation = src.ParseFloat();
		} else if ( !token.Icmp( "noMoveRotation" ) ) {
			noMoveRotation = src.ParseFloat();
		} else if ( !token.Icmp( "minMoveTime" ) ) {
			minMoveTime = src.ParseFloat();
		} else if ( !token.Icmp( "maxMoveTime" ) ) {
			maxMoveTime = src.ParseFloat();
		} else if ( !token.Icmp( "contents" ) ) {
			ParseContents( src, contents );
		} else if ( !token.Icmp( "clipMask" ) ) {
			ParseContents( src, clipMask );
		} else if ( !token.Icmp( "selfCollision" ) ) {
			selfCollision = src.ParseBool();
		} else if ( token == "}" ) {
			break;
		} else {
			src.Error( "unknown token %s in settings", token.c_str() );
			return false;
		}
	}

	return true;
}
コード例 #9
0
ファイル: DeclAF.cpp プロジェクト: anonreclaimer/morpheus
/*
================
idDeclAF::ParseUniversalJoint
================
*/
bool idDeclAF::ParseUniversalJoint( idLexer &src ) {
	idToken token;
	idDeclAF_Constraint *constraint = new idDeclAF_Constraint;

	constraint->SetDefault( this );
	constraints.Alloc() = constraint;

	if ( !src.ExpectTokenType( TT_STRING, 0, &token ) ||
			!src.ExpectTokenString( "{" ) ) {
		return false;
	}

	constraint->type = DECLAF_CONSTRAINT_UNIVERSALJOINT;
	constraint->limit = idDeclAF_Constraint::LIMIT_NONE;
	constraint->name = token;
	constraint->friction = 0.5f;
	constraint->anchor.ToVec3().Zero();
	constraint->shaft[0].ToVec3().Zero();
	constraint->shaft[1].ToVec3().Zero();

	while( src.ReadToken( &token ) ) {

		if ( !token.Icmp( "body1" ) ) {
			src.ExpectTokenType( TT_STRING, 0, &token );
			constraint->body1 = token;
		} else if ( !token.Icmp( "body2" ) ) {
			src.ExpectTokenType( TT_STRING, 0, &token );
			constraint->body2 = token;
		} else if ( !token.Icmp( "anchor" ) ) {
			if ( !constraint->anchor.Parse( src ) ) {
				return false;
			}
		} else if ( !token.Icmp( "shafts" ) ) {
			if ( !constraint->shaft[0].Parse( src ) ||
					!src.ExpectTokenString( "," ) ||
					!constraint->shaft[1].Parse( src ) ) {
				return false;
			}
		} else if ( !token.Icmp( "conelimit" ) ) {
			if ( !constraint->limitAxis.Parse( src ) ||
				!src.ExpectTokenString( "," ) ) {
					return false;
			}
			constraint->limitAngles[0] = src.ParseFloat();
			constraint->limit = idDeclAF_Constraint::LIMIT_CONE;
		} else if ( !token.Icmp( "pyramidlimit" ) ) {
			if ( !constraint->limitAxis.Parse( src ) ||
				!src.ExpectTokenString( "," ) ) {
					return false;
			}
			constraint->limitAngles[0] = src.ParseFloat();
			if ( !src.ExpectTokenString( "," ) ) {
				return false;
			}
			constraint->limitAngles[1] = src.ParseFloat();
			if ( !src.ExpectTokenString( "," ) ) {
				return false;
			}
			constraint->limitAngles[2] = src.ParseFloat();
			constraint->limit = idDeclAF_Constraint::LIMIT_PYRAMID;
		} else if ( !token.Icmp( "friction" ) ) {
			constraint->friction = src.ParseFloat();
		} else if ( token == "}" ) {
			break;
		} else {
			src.Error( "unknown token %s in universal joint", token.c_str() );
			return false;
		}
	}

	return true;
}
コード例 #10
0
ファイル: AASFile.cpp プロジェクト: revelator/Revelator-Doom3
/*
============
idAASSettings::FromParser
============
*/
bool idAASSettings::FromParser( idLexer &src )
{
    idToken token;

    if ( !src.ExpectTokenString( "{" ) )
    {
        return false;
    }

    // parse the file
    while ( 1 )
    {
        if ( !src.ReadToken( &token ) )
        {
            break;
        }

        if ( token == "}" )
        {
            break;
        }

        if ( token == "bboxes" )
        {
            if ( !ParseBBoxes( src ) )
            {
                return false;
            }
        }
        else if ( token == "usePatches" )
        {
            if ( !ParseBool( src, usePatches ) )
            {
                return false;
            }
        }
        else if ( token == "writeBrushMap" )
        {
            if ( !ParseBool( src, writeBrushMap ) )
            {
                return false;
            }
        }
        else if ( token == "playerFlood" )
        {
            if ( !ParseBool( src, playerFlood ) )
            {
                return false;
            }
        }
        else if ( token == "allowSwimReachabilities" )
        {
            if ( !ParseBool( src, allowSwimReachabilities ) )
            {
                return false;
            }
        }
        else if ( token == "allowFlyReachabilities" )
        {
            if ( !ParseBool( src, allowFlyReachabilities ) )
            {
                return false;
            }
        }
        else if ( token == "fileExtension" )
        {
            src.ExpectTokenString( "=" );
            src.ExpectTokenType( TT_STRING, 0, &token );
            fileExtension = token;
        }
        else if ( token == "gravity" )
        {
            ParseVector( src, gravity );
            gravityDir = gravity;
            gravityValue = gravityDir.Normalize();
            invGravityDir = -gravityDir;
        }
        else if ( token == "maxStepHeight" )
        {
            if ( !ParseFloat( src, maxStepHeight ) )
            {
                return false;
            }
        }
        else if ( token == "maxBarrierHeight" )
        {
            if ( !ParseFloat( src, maxBarrierHeight ) )
            {
                return false;
            }
        }
        else if ( token == "maxWaterJumpHeight" )
        {
            if ( !ParseFloat( src, maxWaterJumpHeight ) )
            {
                return false;
            }
        }
        else if ( token == "maxFallHeight" )
        {
            if ( !ParseFloat( src, maxFallHeight ) )
            {
                return false;
            }
        }
        else if ( token == "minFloorCos" )
        {
            if ( !ParseFloat( src, minFloorCos ) )
            {
                return false;
            }
        }
        else if ( token == "tt_barrierJump" )
        {
            if ( !ParseInt( src, tt_barrierJump ) )
            {
                return false;
            }
        }
        else if ( token == "tt_startCrouching" )
        {
            if ( !ParseInt( src, tt_startCrouching ) )
            {
                return false;
            }
        }
        else if ( token == "tt_waterJump" )
        {
            if ( !ParseInt( src, tt_waterJump ) )
            {
                return false;
            }
        }
        else if ( token == "tt_startWalkOffLedge" )
        {
            if ( !ParseInt( src, tt_startWalkOffLedge ) )
            {
                return false;
            }
        }
        else
        {
            src.Error( "invalid token '%s'", token.c_str() );
        }
    }

    if ( numBoundingBoxes <= 0 )
    {
        src.Error( "no valid bounding box" );
    }

    return true;
}
コード例 #11
0
/*
================
idTypeInfoTools::CompareGameState
================
*/
void idTypeInfoTools::CompareGameState( const char *fileName ) {
	int entityNum;
	idToken token;

	src = new idLexer();
	src->SetFlags( LEXFL_NOSTRINGESCAPECHARS );

	if ( !src->LoadFile( fileName ) ) {
		common->Warning( "couldn't load %s", fileName );
		delete src;
		src = NULL;
		return;
	}

	fp = NULL;
	Write = VerifyVariable;

#ifdef DUMP_GAMELOCAL

	if ( !src->ExpectTokenString( "gameLocal" ) || !src->ExpectTokenString( "{" ) ) {
		delete src;
		src = NULL;
		return;
	}

	WriteClass_r( (void *)&gameLocal, "", "idGameLocal", "idGameLocal", "", 0 );

	if ( !src->ExpectTokenString( "}" ) ) {
		delete src;
		src = NULL;
		return;
	}

#endif

	while( src->ReadToken( &token ) ) {
		if ( token != "entity" ) {
			break;
		}
		if ( !src->ExpectTokenType( TT_NUMBER, TT_INTEGER, &token ) ) {
			break;
		}

		entityNum = token.GetIntValue();

		if ( entityNum < 0 || entityNum >= gameLocal.num_entities ) {
			src->Warning( "entity number %d out of range", entityNum );
			break;
		}

		typeError = false;

		idEntity *ent = gameLocal.entities[entityNum];
		if ( !ent ) {
			src->Warning( "entity %d is not spawned", entityNum );
			src->SkipBracedSection( true );
			continue;
		}

		if ( !src->ExpectTokenType( TT_NAME, 0, &token ) ) {
			break;
		}

		if ( token.Cmp( ent->GetType()->classname ) != 0 ) {
			src->Warning( "entity %d has wrong type", entityNum );
			src->SkipBracedSection( true );
			continue;
		}

		if ( !src->ExpectTokenString( "{" ) ) {
			src->Warning( "entity %d missing leading {", entityNum );
			break;
		}

		WriteClass_r( (void *)ent, "", ent->GetType()->classname, ent->GetType()->classname, "", 0 );

		if ( !src->SkipBracedSection( false ) ) {
			src->Warning( "entity %d missing trailing }", entityNum );
			break;
		}
	}

	delete src;
	src = NULL;
}