/* ============================ 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); } } }
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 ); } }
/* ============================ 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; } }
/* ============================ 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); }
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; } } }