示例#1
0
/*
============================
JKG_ParseAmmoOverride_Float

Parses a single ammo override
============================
*/
static void JKG_ParseAmmoOverride_Float(cJSON* json, const char* name, complexAmmoOverride<double>& field) {
	cJSON* node = cJSON_GetObjectItem(json, name);
	if (!node) {
		field.bIsPresent = qfalse;
	}
	else {
		cJSON* child;

		field.bIsPresent = qtrue;
		field.bAdd = qfalse;
		field.bSet = qfalse;
		field.bMultiply = qfalse;

		child = cJSON_GetObjectItem(node, "set");
		if (child) {
			field.bSet = qtrue;
			field.set = cJSON_ToNumber(child);
		}

		child = cJSON_GetObjectItem(node, "add");
		if (child) {
			field.bAdd = qtrue;
			field.add = cJSON_ToNumber(child);
		}

		child = cJSON_GetObjectItem(node, "multiply");
		if (child) {
			field.bMultiply = qtrue;
			field.multiply = cJSON_ToNumber(child);
		}
	}
}
示例#2
0
void JPLua_Serialiser_IterateTableRead( cJSON *parent, const char *name, lua_State *L ) {
	cJSON *t = NULL;
	int numElements, i, top;

	lua_newtable( L );
	top = lua_gettop( L );

	t = cJSON_GetObjectItem( parent, name );
	numElements = cJSON_GetArraySize( t );

	for ( i = 0; i < numElements; i++ ) {
		cJSON *e, *it;
		int kType, vType;
		const char *tmp;
		char k[256];

		e = cJSON_GetArrayItem( t, i );

		// key
		it = cJSON_GetObjectItem( e, "key" );
		kType = cJSON_ToInteger( cJSON_GetObjectItem( e, "key_type" ) );
		if ( (tmp = cJSON_ToString( it )) )
			Q_strncpyz( k, tmp, sizeof(k) );

		if ( kType == LUA_TSTRING ) {
			lua_pushstring( L, k );
		}
		else if ( kType == LUA_TNUMBER ) {
			lua_pushnumber( L, cJSON_ToNumber( it ) );
		}
		else {
			Com_Printf( "Invalid key type %s when reading table %s\n", lua_typename( L, kType ), name );
		}

		// value must be created based on type.
		it = cJSON_GetObjectItem( e, "value" );
		vType = cJSON_ToInteger( cJSON_GetObjectItem( e, "value_type" ) );
		if ( vType == LUA_TTABLE ) {
			JPLua_Serialiser_IterateTableRead( e, "value", L );
		}
		else if ( vType == LUA_TNUMBER ) {
			lua_pushnumber( L, cJSON_ToNumber( it ) );
		}
		else if ( vType == LUA_TBOOLEAN ) {
			lua_pushboolean( L, cJSON_ToBoolean( it ) );
		}
		else if ( vType == LUA_TSTRING ) {
			char v[1024 * 8]; // should be plenty..
			if ( (tmp = cJSON_ToString( it )) )
				Q_strncpyz( v, tmp, sizeof(v) );
			lua_pushstring( L, v );
		}

		lua_settable( L, top );
	}
}
示例#3
0
/*
============================
JKG_ParseSimpleOverrideVec3

============================
*/
static void JKG_ParseSimpleOverrideVec3(std::pair<qboolean, vec3_t>& field, const char* nodeName, cJSON* json)
{
	cJSON* child = cJSON_GetObjectItem(json, nodeName);
	int max;

	if (child)
	{
		field.first = qtrue;
		max = cJSON_GetArraySize(child);
		if (max != 3)
		{
			field.second[0] = field.second[1] = field.second[2] = 1.0f;
		}
		else
		{
			for (int i = 0; i < max; i++)
			{
				field.second[i] = cJSON_ToNumber(cJSON_GetArrayItem(child, i));
			}
		}
	}
	else
	{
		field.first = qfalse;
	}
}
示例#4
0
/*
============================
JKG_ParseSimpleOverrideFloat

============================
*/
static void JKG_ParseSimpleOverrideFloat(std::pair<qboolean, float>& field, const char* nodeName, cJSON* json)
{
	cJSON* child = cJSON_GetObjectItem(json, nodeName);
	if (child)
	{
		field.first = qtrue;
		field.second = cJSON_ToNumber(child);
	}
	else
	{
		field.first = qfalse;
	}
}
static int GLua_JSON_ToNumber( lua_State *L )
{
	// Check and make sure we're using a valid index
	if( !FJSON_ValidateNode( L, 1 ) )
	{
		lua_pushnil(L);
		return 1;
	}

	// Convert to number
	int index = luaL_checkint( L, 1 );
	double number = cJSON_ToNumber( fJSON.jsonBinding.at( index ) );

	lua_pushnumber( L, number );
	return 1;
}
static void ParseAmmoFile ( const char *fileText )
{
	int i = 0;
    cJSON *json = NULL;
    char jsonError[MAX_STRING_CHARS] = { 0 };

    json = cJSON_ParsePooled (fileText, jsonError, sizeof (jsonError));
    if ( json == NULL )
    {
        Com_Printf (S_COLOR_RED "Error: %s\n", jsonError);
    }
    else
    {
        ammo_t *ammo = &ammoTable[0];
        cJSON *jsonNode;
        cJSON *field;
        const char *string = NULL;
        
        for ( jsonNode = cJSON_GetFirstItem (json); jsonNode; jsonNode = cJSON_GetNextItem (jsonNode), ammo++, numAmmoLoaded++, i++ )
        {
            field = cJSON_GetObjectItem (jsonNode, "name");
            string = cJSON_ToString (field);
			if(string && string[0])
				Q_strncpyz (ammo->name, string, sizeof (ammo->name));

			field = cJSON_GetObjectItem (jsonNode, "ammoMax");
			ammo->ammoMax = cJSON_ToNumber(field);

			ammo->ammoIndex = i;
            
            #ifdef _CGAME
            {
                cJSON *visual = cJSON_GetObjectItem (jsonNode, "visual");
                if ( visual )
                {
                    cJSON *child = NULL;
                
                    field = cJSON_GetObjectItem (visual, "model");
                    string = cJSON_ToString (field);
                    if ( string && string[0] )
                    {
                        ammo->model = trap->R_RegisterModel (string);
                    }
                    
                    field = cJSON_GetObjectItem (visual, "fx");
                    string = cJSON_ToString (field);
                    if ( string && string[0] )
                    {
                        ammo->fx = trap->FX_RegisterEffect (string);
                    }
                    
                    field = cJSON_GetObjectItem (visual, "deathfx");
                    string = cJSON_ToString (field);
                    if ( string && string[0] )
                    {
                        ammo->deathFx = trap->FX_RegisterEffect (string);
                    }
                    
                    child = cJSON_GetObjectItem (visual, "miss");
                    if ( child )
                    {
                        field = cJSON_GetObjectItem (child, "impactfx");
                        string = cJSON_ToString (field);
                        if ( string && string[0] )
                        {
                            ammo->missFx = trap->FX_RegisterEffect (string);
                        }
                    }
                    
                    child = cJSON_GetObjectItem (visual, "hit");
                    if ( child )
                    {
                        field = cJSON_GetObjectItem (child, "impactfx");
                        string = cJSON_ToString (field);
                        if ( string && string[0] )
                        {
                            ammo->hitFx = trap->FX_RegisterEffect (string);
                        }
                    }
                }
            }
            #endif
        }
    }
    
    cJSON_Delete (json);
    
    Com_Printf ("Successfully loaded %d ammo types.\n", numAmmoLoaded);
}
示例#7
0
static void JKG_ParseBuffOverrides(ammo_t* ammo, cJSON* json, const char* nodeName)
{
	cJSON* child = cJSON_GetObjectItem(json, nodeName);
	if (child == nullptr)
	{
		return;
	}

	int elemCount = cJSON_GetArraySize(child);
	if (elemCount <= 0)
	{
		return; // not actually an array
	}

	// Iterate through each buff array item
	for (int i = 0; i < elemCount; i++)
	{
		cJSON* buff = cJSON_GetArrayItem(child, i);
		complexAmmoBuffOverride buffOverride = { 0 };

		cJSON* buffChild = cJSON_GetObjectItem(buff, "buff");
		if (buffChild == nullptr)
		{	// JSON doesn't contain a "buff" field. Continue.
			continue;
		}

		buffOverride.buff = JKG_ResolveBuffName(cJSON_ToStringOpt(buffChild, ""));
		if (buffOverride.buff < 0)
		{	// A buff by this name doesn't exist, continue.
			continue;
		}

		buffChild = cJSON_GetObjectItem(buff, "remove");
		buffOverride.bRemove = cJSON_ToBooleanOpt(buffChild, qfalse);

		buffChild = cJSON_GetObjectItem(buff, "addbuff");
		buffOverride.bAddBuff = cJSON_ToBooleanOpt(buffChild, qfalse);

		buffChild = cJSON_GetObjectItem(buff, "duration");
		if (buffChild != nullptr)
		{
			cJSON* childProps;

			childProps = cJSON_GetObjectItem(buffChild, "add");
			if (childProps != nullptr)
			{
				buffOverride.bAddDuration = qtrue;
				buffOverride.addDuration = cJSON_ToInteger(childProps);
			}

			childProps = cJSON_GetObjectItem(buffChild, "multiply");
			if (childProps != nullptr)
			{
				buffOverride.bMultiplyDuration = qtrue;
				buffOverride.multiplyDuration = cJSON_ToNumber(childProps);
			}

			childProps = cJSON_GetObjectItem(buffChild, "set");
			if (childProps != nullptr)
			{
				buffOverride.bSetDuration = qtrue;
				buffOverride.setDuration = cJSON_ToInteger(childProps);
			}
		}

		buffChild = cJSON_GetObjectItem(buff, "intensity");
		if (buffChild != nullptr)
		{
			cJSON* childProps;

			childProps = cJSON_GetObjectItem(buffChild, "add");
			if (childProps != nullptr)
			{
				buffOverride.bAddIntensity = qtrue;
				buffOverride.addIntensity = cJSON_ToNumber(childProps);
			}

			childProps = cJSON_GetObjectItem(buffChild, "multiply");
			if (childProps != nullptr)
			{
				buffOverride.bMultiplyIntensity = qtrue;
				buffOverride.multiplyIntensity = cJSON_ToNumber(childProps);
			}

			childProps = cJSON_GetObjectItem(buffChild, "set");
			if (childProps != nullptr)
			{
				buffOverride.bSetIntensity = qtrue;
				buffOverride.setIntensity = cJSON_ToNumber(childProps);
			}
		}

		// Add the override to the list of buff overrides
		ammo->overrides.buffs.emplace_back(buffOverride);
	}
}
static qboolean BG_ParseWeaponFile ( const char *weaponFilePath )
{
    cJSON *json = NULL;
    cJSON *jsonNode = NULL;
    char error[MAX_STRING_CHARS];
    const char *str = NULL;
    int weapon;
	int i;
    
    char weaponFileData[MAX_WEAPON_FILE_LENGTH];
    fileHandle_t f;
    int fileLen = strap_FS_FOpenFile (weaponFilePath, &f, FS_READ);
    
    weaponData_t weaponData;

	fmLoadCounter = 0;
    
    if ( !f || fileLen == -1 )
    {
        Com_Printf (S_COLOR_RED "%s: failed to read the weapon file. File is unreadable or is empty.\n", weaponFilePath);
        return qfalse;
    }
    
    if ( (fileLen + 1) >= MAX_WEAPON_FILE_LENGTH )
    {
        trap_FS_FCloseFile (f);
        Com_Printf (S_COLOR_RED "%s: file too big (%d bytes, maximum is %d).\n", weaponFilePath, fileLen, MAX_WEAPON_FILE_LENGTH - 1);
        
        return qfalse;
    }
    
    strap_FS_Read (&weaponFileData, fileLen, f);
    weaponFileData[fileLen] = '\0';
    
    strap_FS_FCloseFile (f);
    
    json = cJSON_ParsePooled (weaponFileData, error, sizeof (error));
    if ( json == NULL )
    {
        Com_Printf (S_COLOR_RED "%s: %s\n", weaponFilePath, error);
        
        return qfalse;
    }
    
    BG_InitializeWeaponData (&weaponData);
    
    ReadString (json, "classname", weaponData.classname, sizeof (weaponData.classname));
    
    jsonNode = cJSON_GetObjectItem (json, "type");
    str = cJSON_ToString (jsonNode);
    weapon = GetIDForString (WPTable, str);
    weaponData.weaponBaseIndex = weapon;
    
    jsonNode = cJSON_GetObjectItem (json, "variation");
    weapon = cJSON_ToNumber (jsonNode);
    weaponData.weaponModIndex = weapon;

    jsonNode = cJSON_GetObjectItem (json, "stats");
    BG_ParseWeaponStats (&weaponData, jsonNode);
    
	weaponData.numFiringModes = 0;
	for(i = 0; i < MAX_FIREMODES; i++)
	{
		jsonNode = cJSON_GetObjectItem (json, va("firemode%i", i));
		if(jsonNode != NULL)
		{
			BG_ParseWeaponFireMode (&weaponData.firemodes[i], jsonNode);
			weaponData.numFiringModes++;
		}
	}
	// Old stuff for when we had primary/alt attacks --eez
    /*jsonNode = cJSON_GetObjectItem (json, "primaryattack");
    BG_ParseWeaponFireMode (&weaponData.firemodes[0], jsonNode);
    
    jsonNode = cJSON_GetObjectItem (json, "secondaryattack");
    if ( jsonNode != NULL )
    {
        weaponData.hasSecondary = 1;
        BG_ParseWeaponFireMode (&weaponData.firemodes[1], jsonNode);
    }*/
    
    jsonNode = cJSON_GetObjectItem (json, "playeranims");
    BG_ParseWeaponPlayerAnimations (&weaponData, jsonNode);
    
    jsonNode = cJSON_GetObjectItem (json, "name");
    str = cJSON_ToString (jsonNode);
    Q_strncpyz (weaponData.displayName, str, sizeof (weaponData.displayName));
    
#ifdef CGAME
    // TODO: Maybe we can turn this into a loop somehow? It's just turning into a stupidly long list.

    jsonNode = cJSON_GetObjectItem (json, "weaponanims");
    // TODO
    
    jsonNode = cJSON_GetObjectItem (json, "description");
    str = cJSON_ToString (jsonNode);
    Q_strncpyz (weaponData.visuals.description, str, sizeof (weaponData.visuals.description));
    
    jsonNode = cJSON_GetObjectItem (json, "visual");
    BG_ParseVisuals (&weaponData, jsonNode);
#endif
    

    /*if ( weaponData.zoomType != ZOOM_NONE )
    {
        // If we have zoom mode, then copy over the data from the primary to the secondary
        // so it's as if we haven't changed fire modes at all! Ingenious! (And also temporary)
        weaponData.firemodes[1] = weaponData.firemodes[0];
    }*/
    
    BG_AddWeaponData (&weaponData);
    
    cJSON_Delete (json);
    
    return qtrue;
}
static void BG_ParseVisualsFireMode ( weaponVisualFireMode_t *fireMode, cJSON *fireModeNode, int numFireModes )
{
    cJSON *node = NULL;
    cJSON *child = NULL;
    qboolean isGrenade = qfalse;
    qboolean isBlaster = qfalse;
    qboolean isTripmine = qfalse;
    qboolean isDetpack = qfalse;

    ReadString (fireModeNode, "type", fireMode->type, sizeof (fireMode->type));
    isGrenade = (qboolean)(Q_stricmp (fireMode->type, "grenade") == 0);
    isBlaster = (qboolean)(Q_stricmp (fireMode->type, "blaster") == 0);
    isTripmine = (qboolean)(Q_stricmp (fireMode->type, "tripmine") == 0);
    isDetpack = (qboolean)(Q_stricmp (fireMode->type, "detpack") == 0);

	ReadString (fireModeNode, "displayName", fireMode->displayName, 128);

	ReadString (fireModeNode, "crosshairShader", fireMode->crosshairShader, MAX_QPATH);
	ReadString (fireModeNode, "switchToSound", fireMode->switchToSound, MAX_QPATH);
	if(!fireMode->switchToSound || !fireMode->switchToSound[0])
	{
		if(fmLoadCounter == 0)
		{
			Com_sprintf(fireMode->switchToSound, MAX_QPATH, "sound/weapons/common/click%i.wav", numFireModes);
		}
		else
		{
			Com_sprintf(fireMode->switchToSound, MAX_QPATH, "sound/weapons/common/click1.wav");
		}
	}

	node = cJSON_GetObjectItem (fireModeNode, "animType");
    fireMode->animType = (firingModeAnim_t)cJSON_ToInteger (node);

	fireMode->overrideIndicatorFrame = -1;											// set this as default since 0 is still a valid frame
	node = cJSON_GetObjectItem (fireModeNode, "overrideIndicatorFrame");
	if(node)
	{
		fireMode->overrideIndicatorFrame = cJSON_ToInteger (node);
	}
    
    // TODO: Need to tie this to the table in cg_weapons.c somehow...
    // Weapon Render
    node = cJSON_GetObjectItem (fireModeNode, "muzzlelightintensity");
    fireMode->weaponRender.generic.muzzleLightIntensity = (float)cJSON_ToNumber (node);
    
    ReadString (fireModeNode, "muzzlelightcolor", fireMode->weaponRender.generic.muzzleLightColor, sizeof (fireMode->weaponRender.generic.muzzleLightColor));
    ReadString (fireModeNode, "chargingfx", fireMode->weaponRender.generic.chargingEffect, sizeof (fireMode->weaponRender.generic.chargingEffect));    
    ReadString (fireModeNode, "muzzlefx", fireMode->weaponRender.generic.muzzleEffect, sizeof (fireMode->weaponRender.generic.muzzleEffect));
    
    // Weapon Fire
    child = cJSON_GetObjectItem (fireModeNode, "firesound");
    if ( child )
    {
        if ( cJSON_IsArray (child) )
        {
            const char *fireSounds[8];
            int numFireSounds = cJSON_ReadStringArray (child, 8, fireSounds);
            int i;
            
            for ( i = 0; i < numFireSounds; i++ )
            {
                Q_strncpyz (fireMode->weaponFire.generic.fireSound[i], fireSounds[i], sizeof (fireMode->weaponFire.generic.fireSound[i]));
            }
        }
        else
        {
            const char *s = cJSON_ToString (child);
            if ( s ) Q_strncpyz (fireMode->weaponFire.generic.fireSound[0], s, sizeof (fireMode->weaponFire.generic.fireSound[0]));
        }
    }
    
    // Traceline Render
    ReadString (fireModeNode, "tracelineshader", fireMode->tracelineRender.generic.tracelineShader, sizeof (fireMode->tracelineRender.generic.tracelineShader));
    
    node = cJSON_GetObjectItem (fireModeNode, "minsize");
    fireMode->tracelineRender.generic.minSize = (float)cJSON_ToNumber (node);
    
    node = cJSON_GetObjectItem (fireModeNode, "maxsize");
    fireMode->tracelineRender.generic.maxSize = (float)cJSON_ToNumber (node);
    
    node = cJSON_GetObjectItem (fireModeNode, "lifetime");
    fireMode->tracelineRender.generic.lifeTime = cJSON_ToInteger (node);
    
    // Weapon Charge
    ReadString (fireModeNode, "chargingsound", fireMode->weaponCharge.chargingSound, sizeof (fireMode->weaponCharge.chargingSound));
    
    // Projectile render
    ReadString (fireModeNode, "projectilemodel", fireMode->projectileRender.generic.projectileModel, sizeof (fireMode->projectileRender.generic.projectileModel));
    ReadString (fireModeNode, "projectilefx", fireMode->projectileRender.generic.projectileEffect, sizeof (fireMode->projectileRender.generic.projectileEffect));
    ReadString (fireModeNode, "runsound", fireMode->projectileRender.generic.runSound, sizeof (fireMode->projectileRender.generic.runSound));
    
    node = cJSON_GetObjectItem (fireModeNode, "lightintensity");
    fireMode->projectileRender.generic.lightIntensity = (float)cJSON_ToNumber (node);
    
    ReadString (fireModeNode, "lightcolor", fireMode->projectileRender.generic.lightColor, sizeof (fireMode->projectileRender.generic.lightColor));
  
    ReadString (fireModeNode, "deathfx", fireMode->projectileRender.generic.deathEffect, sizeof (fireMode->projectileRender.generic.deathEffect));
    
    // Projectile miss event
    child = cJSON_GetObjectItem (fireModeNode, "miss");
    if ( isTripmine || isDetpack )
    {
        ReadString (child, "sticksound", fireMode->projectileMiss.explosive.stickSound, sizeof (fireMode->projectileMiss.explosive.stickSound));
    }
    else
    {
        ReadString (child, "impactfx", fireMode->projectileMiss.generic.impactEffect, sizeof (fireMode->projectileMiss.generic.impactEffect));
        ReadString (child, "shockwavefx", fireMode->projectileMiss.grenade.shockwaveEffect, sizeof (fireMode->projectileMiss.grenade.shockwaveEffect));
    }
    
    // Projectile hit event
    child = cJSON_GetObjectItem (fireModeNode, "hit");
    ReadString (child, "impactfx", fireMode->projectileHitPlayer.generic.impactEffect, sizeof (fireMode->projectileHitPlayer.generic.impactEffect));
    ReadString (child, "shockwavefx", fireMode->projectileHitPlayer.grenade.shockwaveEffect, sizeof (fireMode->projectileHitPlayer.grenade.shockwaveEffect));
    
    // Projectile deflected event
    ReadString (fireModeNode, "deflectedfx", fireMode->projectileDeflected.generic.deflectEffect, sizeof (fireMode->projectileDeflected.generic.deflectEffect));
    
    // Grenade bounce event
    child = cJSON_GetObjectItem (fireModeNode, "bouncesound");
    if ( child )
    {
        const char *bounceSounds[2];
        int numBounceSounds = cJSON_ReadStringArray (child, 2, bounceSounds);
        int i;
        
        for ( i = 0; i < numBounceSounds; i++ )
        {
            Q_strncpyz (fireMode->grenadeBounce.grenade.bounceSound[i], bounceSounds[i], sizeof (fireMode->grenadeBounce.grenade.bounceSound[i]));
        }
    }
    
    // Explosive render
    ReadString (fireModeNode, "g2model", fireMode->explosiveRender.detpack.g2Model, sizeof (fireMode->explosiveRender.detpack.g2Model));
    
    node = cJSON_GetObjectItem (fireModeNode, "g2radius");
    fireMode->explosiveRender.detpack.g2Radius = (float)cJSON_ToNumber (node);
    
    ReadString (fireModeNode, "linefx", fireMode->explosiveRender.tripmine.lineEffect, sizeof (fireMode->explosiveRender.tripmine.lineEffect));
    
    // Explosive blow event
    ReadString (fireModeNode, "explodefx", fireMode->explosiveBlow.generic.explodeEffect, sizeof (fireMode->explosiveBlow.generic.explodeEffect));
    
    // Explosive armed event
    ReadString (fireModeNode, "armsound", fireMode->explosiveArm.armSound, sizeof (fireMode->explosiveArm.armSound));

	fmLoadCounter++;
}
static void BG_ParseWeaponPlayerAnimations ( weaponData_t *weaponData, cJSON *playerAnimNode )
{
    cJSON *node;
    
    node = cJSON_GetObjectItem (playerAnimNode, "ready");
	if(node)
	{
		BG_ParseAnimationObject (node, &weaponData->anims.ready.torsoAnim, &weaponData->anims.ready.legsAnim);
	}
    
    node = cJSON_GetObjectItem (playerAnimNode, "firing");
	if(node)
	{
		BG_ParseAnimationObject (node, &weaponData->anims.firing.torsoAnim, &weaponData->anims.firing.legsAnim);
	}
    
    /*node = cJSON_GetObjectItem (playerAnimNode, "idle");
    BG_ParseAnimationObject (node, &weaponData->torsoFiringAnimation, &weaponData->legsFiringAnimation);
    
    node = cJSON_GetObjectItem (playerAnimNode, "drop");
    BG_ParseAnimationObject (node, &weaponData->torsoFiringAnimation, &weaponData->legsFiringAnimation);
    
    node = cJSON_GetObjectItem (playerAnimNode, "raise");
    BG_ParseAnimationObject (node, &weaponData->torsoFiringAnimation, &weaponData->legsFiringAnimation);*/

	
    
    node = cJSON_GetObjectItem (playerAnimNode, "reload");
	if(node)
	{
		BG_ParseAnimationObject (node, &weaponData->anims.reload.torsoAnim, &weaponData->anims.reload.legsAnim);
	}

	node = cJSON_GetObjectItem (playerAnimNode, "backwardWalk");
	if(node)
	{
		BG_ParseAnimationObject (node, &weaponData->anims.backwardWalk.torsoAnim, &weaponData->anims.backwardWalk.legsAnim);
	}

	node = cJSON_GetObjectItem (playerAnimNode, "forwardWalk");
	if(node)
	{
		BG_ParseAnimationObject (node, &weaponData->anims.forwardWalk.torsoAnim, &weaponData->anims.forwardWalk.legsAnim);
	}

	node = cJSON_GetObjectItem (playerAnimNode, "crouchWalk");
	if(node)
	{
		BG_ParseAnimationObject (node, &weaponData->anims.crouchWalk.torsoAnim, &weaponData->anims.crouchWalk.legsAnim);
	}

	node = cJSON_GetObjectItem (playerAnimNode, "crouchWalkBack");
	if(node)
	{
		BG_ParseAnimationObject (node, &weaponData->anims.crouchWalkBack.torsoAnim, &weaponData->anims.crouchWalkBack.legsAnim);
	}

	node = cJSON_GetObjectItem (playerAnimNode, "jump");
	if(node)
	{
		BG_ParseAnimationObject (node, &weaponData->anims.jump.torsoAnim, &weaponData->anims.jump.legsAnim);
	}

	node = cJSON_GetObjectItem (playerAnimNode, "land");
	if(node)
	{
		BG_ParseAnimationObject (node, &weaponData->anims.land.torsoAnim, &weaponData->anims.land.legsAnim);
	}

	node = cJSON_GetObjectItem (playerAnimNode, "run");
	if(node)
	{
		BG_ParseAnimationObject (node, &weaponData->anims.run.torsoAnim, &weaponData->anims.run.legsAnim);
	}

	node = cJSON_GetObjectItem (playerAnimNode, "sprint");
	if(node)
	{
		BG_ParseAnimationObject (node, &weaponData->anims.sprint.torsoAnim, &weaponData->anims.sprint.legsAnim);
	}

	node = cJSON_GetObjectItem (playerAnimNode, "sprintStyle");
	if(node)
	{
		weaponData->firstPersonSprintStyle = cJSON_ToNumber(node);
	}
}
static void BG_ParseDamage ( weaponFireModeStats_t *fireModeStats, cJSON *damageNode, qboolean secondary )
{
    if ( !damageNode )
    {
        return;
    }
    
    if ( !secondary && cJSON_IsNumber (damageNode) )
    {
        fireModeStats->baseDamage = (short)cJSON_ToIntegerOpt (damageNode, 0);
    }
    else if ( cJSON_IsObject (damageNode) )
    {
        damageSettings_t darea;
        cJSON *node = NULL;
        qhandle_t areaHandle = 0;
        
        memset (&darea, 0, sizeof (darea));
        
        node = cJSON_GetObjectItem (damageNode, "damageradius");
        if ( node )
        {
            cJSON *child = NULL;
            const char *s = NULL;
            
            darea.radial = qtrue;
            
            child = cJSON_GetObjectItem (node, "start");
            darea.radiusParams.startRadius = (float)cJSON_ToNumber (child);
            
            child = cJSON_GetObjectItem (node, "end");
            darea.radiusParams.endRadius = (float)cJSON_ToNumber (child);
            
            child = cJSON_GetObjectItem (node, "parm");
            darea.radiusParams.generic1 = cJSON_ToInteger (child);
            
            child = cJSON_GetObjectItem (node, "falloff");
            s = cJSON_ToStringOpt (child, "constant");
            if ( Q_stricmp (s, "constant") == 0 )
                darea.radiusParams.damageFunc = DF_CONSTANT;
            else if ( Q_stricmp (s, "linear") == 0 )
                darea.radiusParams.damageFunc = DF_LINEAR;
            else if ( Q_stricmp (s, "gaussian") == 0 )
                darea.radiusParams.damageFunc = DF_GAUSSIAN;
            else
            {
                darea.radiusParams.damageFunc = DF_CONSTANT;
                Com_Printf ("Unknown damage falloff type used: %s. Defaulting to linear falloff.\n", s);
            }
                
            child = cJSON_GetObjectItem (node, "function");
            s = cJSON_ToStringOpt (child, "constant");
            if ( Q_stricmp (s, "linear") == 0 )
                darea.radiusParams.radiusFunc = RF_LINEAR;
            else if ( Q_stricmp (s, "nonlinear") == 0 )
                darea.radiusParams.radiusFunc = RF_NONLINEAR;
            else if ( Q_stricmp (s, "clamp") == 0 )
                darea.radiusParams.radiusFunc = RF_CLAMP;
            else if ( Q_stricmp (s, "wave") == 0 )
                darea.radiusParams.radiusFunc = RF_WAVE;
            else if ( Q_stricmp (s, "constant") == 0 )
                darea.radiusParams.radiusFunc = RF_CONSTANT;
            else
            {
                darea.radiusParams.radiusFunc = RF_CONSTANT;
                Com_Printf ("Unknown radius function used: %s; Defaulting to constant radius.\n", s);
            }
        }
        
        node = cJSON_GetObjectItem (damageNode, "duration");
        darea.lifetime = cJSON_ToIntegerOpt (node, 0);
        
        node = cJSON_GetObjectItem (damageNode, "delay");
        darea.delay = cJSON_ToIntegerOpt (node, 0);
        
        node = cJSON_GetObjectItem (damageNode, "damage");
        darea.damage = cJSON_ToIntegerOpt (node, 0);
        fireModeStats->baseDamage = darea.damage;
        
        node = cJSON_GetObjectItem (damageNode, "damagedelay");
        darea.damageDelay = cJSON_ToIntegerOpt (node, 0);
        
        node = cJSON_GetObjectItem (damageNode, "penetration");
        switch ( cJSON_ToIntegerOpt (node, 0) )
        {
            default:
            case 0: darea.penetrationType = PT_NONE; break;
            case 1: darea.penetrationType = PT_SHIELD; break;
            case 2: darea.penetrationType = PT_SHIELD_ARMOR; break;
            case 3: darea.penetrationType = PT_SHIELD_ARMOR_BUILDING; break;
        }
        
        node = cJSON_GetObjectItem (damageNode, "damagetype");
        if ( node )
        {
            int i = 0;
            const char *types[NUM_DAMAGE_TYPES];
            int numTypes = cJSON_ReadStringArray (node, NUM_DAMAGE_TYPES, types);
            
            for ( i = 0; i < numTypes; i++ )
            {
                if ( Q_stricmp (types[i], "annihilate") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_ANNIHILATION);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "concussion") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_CONCUSSION);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "cut") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_CUT);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "disintegrate") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_DISINTEGRATE);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "electric") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_ELECTRIC);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "explosion") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_EXPLOSION);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "fire") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= ( 1 << DT_FIRE );
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "freeze") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_FREEZE);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "implosion") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_IMPLOSION);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "stun") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_STUN);
                    darea.damageType = dType;
				}
                else if ( Q_stricmp (types[i], "carbonite") == 0 )
				{
					int dType = (int)darea.damageType;
					dType |= (1 << DT_CARBONITE);
                    darea.damageType = dType;
				}
                else
				{
                    Com_Printf ("Unknown damage type used: %s.\n", types[i]);
				}
            }
        }
        
        areaHandle = JKG_RegisterDamageSettings (&darea);
        if ( !secondary )
        {
            fireModeStats->damageTypeHandle = areaHandle;
        }
        else
        {
            fireModeStats->secondaryDmgHandle = areaHandle;
        }
    }
}