//========================================================= // BG_ParseWeaponStats //--------------------------------------------------------- // Description: // Parses the stats block of a weapons file. //========================================================= static void BG_ParseWeaponStats ( weaponData_t *weaponData, cJSON *statsNode ) { cJSON *node; const char *flags[4]; const char *ammo; if ( statsNode == NULL ) { return; } node = cJSON_GetObjectItem (statsNode, "slot"); weaponData->weaponSlot = (unsigned char)cJSON_ToIntegerOpt (node, 0); node = cJSON_GetObjectItem (statsNode, "reloadtime"); weaponData->weaponReloadTime = (unsigned short)cJSON_ToIntegerOpt (node, 0); node = cJSON_GetObjectItem (statsNode, "ammoIndex"); ammo = cJSON_ToStringOpt (node, "AMMO_NONE"); weaponData->ammoIndex = BG_GetAmmo(ammo)->ammoIndex; node = cJSON_GetObjectItem (statsNode, "ammoOnSpawn"); weaponData->ammoOnSpawn = (unsigned int)cJSON_ToIntegerOpt (node, ((weaponData->ammoIndex < AMMO_ROCKETS) ? 400 : ((weaponData->ammoIndex != AMMO_ROCKETS) ? 444 : 10))); // Gives 300 ammo for non-explosives node = cJSON_GetObjectItem (statsNode, "ammoOnPickup"); weaponData->ammoOnPickup = (unsigned int)cJSON_ToIntegerOpt (node, ((weaponData->ammoIndex < AMMO_ROCKETS) ? 20 : 1)); // Gives 20 ammo for non-explosives node = cJSON_GetObjectItem (statsNode, "clipSize"); weaponData->clipSize = (unsigned int)cJSON_ToIntegerOpt (node, 0); node = cJSON_GetObjectItem (statsNode, "flags"); if ( node != NULL ) { int numFlags = cJSON_ReadStringArray (node, 4, flags); int i; for ( i = 0; i < numFlags; i++ ) { BG_ParseWeaponStatsFlags (weaponData, flags[i]); } } node = cJSON_GetObjectItem (statsNode, "speed"); weaponData->speedModifier = (float)cJSON_ToNumberOpt (node, 1.0); node = cJSON_GetObjectItem (statsNode, "reloadmodifier"); weaponData->reloadModifier = (float)cJSON_ToNumberOpt (node, 1.0); node = cJSON_GetObjectItem (statsNode, "startzoomfov"); weaponData->startZoomFov = (float)cJSON_ToNumberOpt (node, 50.0); node = cJSON_GetObjectItem (statsNode, "endzoomfov"); weaponData->endZoomFov = (float)cJSON_ToNumberOpt (node, weaponData->zoomType == ZOOM_TOGGLE ? weaponData->startZoomFov : 5.0); node = cJSON_GetObjectItem (statsNode, "zoomtime"); weaponData->zoomTime = cJSON_ToIntegerOpt (node, 2000); node = cJSON_GetObjectItem (statsNode, "ironsightsTime"); weaponData->ironsightsTime = cJSON_ToIntegerOpt (node, IRONSIGHTS_TIME); }
/* ============================ JKG_ParseSingleAmmo Reads a single ammo entry from a .ammo file ============================ */ static qboolean JKG_ParseSingleAmmo(cJSON* json) { const char* name = cJSON_GetItemKey(json); ammo_t* ammo = &ammoTable[numAmmoLoaded]; cJSON* child; ammo->ammoIndex = numAmmoLoaded; Q_strncpyz(ammo->name, name, sizeof(ammo->name)); Q_strncpyz(ammo->shortname, cJSON_ToStringOpt(cJSON_GetObjectItem(json, "shortname"), ""), sizeof(ammo->shortname)); // Parse substitutes (we need to establish the link later) ammo->pSub = nullptr; child = cJSON_GetObjectItem(json, "basedOn"); if (child) { Q_strncpyz(ammo->substitute, cJSON_ToString(child), sizeof(ammo->substitute)); } else { Q_strncpyz(ammo->substitute, ammo->name, sizeof(ammo->substitute)); } child = cJSON_GetObjectItem(json, "max"); ammo->ammoMax = cJSON_ToIntegerOpt(child, 999); child = cJSON_GetObjectItem(json, "pricePerUnit"); ammo->pricePerUnit = cJSON_ToNumberOpt(child, 1.0); child = cJSON_GetObjectItem(json, "overrides"); if (child) { JKG_ParseAmmoOverrides(ammo, child); } return qtrue; }
int termsMasterFinalFunc (asyncTask_t *task) { cJSON *data = (cJSON *)task->finalData; if (task->errorCode == 0) { Com_Printf("Terms of use:\n%s\n", cJSON_ToStringOpt(cJSON_GetObjectItem(data, "message"), "")); } else { Com_Printf("Could not obtain terms of use!\n"); } return 0; }
static int GLua_JSON_ToStringOpt( lua_State *L ) { // Check and make sure we're using a valid index if( !FJSON_ValidateNode( L, 1 ) ) { lua_pushnil(L); return 1; } cJSON *node = FJSON_RetrieveNode( L, 1 ); lua_pushstring( L, cJSON_ToStringOpt( node, luaL_checkstring( L, 2 ) ) ); return 1; }
/* =================== CG_ParseLoadingScreenTips =================== */ void CG_ParseLoadingScreenTips(void) { fileHandle_t f; int len = trap->FS_Open("ext_data/tables/loadingTips.json", &f, FS_READ); char* buffer; char error[1024]; memset(error, 0, sizeof(error)); if (len == 0 || f == NULL_HANDLE) { Com_Printf("No loading tips to display\n"); return; } trap->TrueMalloc((void**)&buffer, len); if (buffer == nullptr) { return; } trap->FS_Read(buffer, len, f); trap->FS_Close(f); cJSON* json = cJSON_ParsePooled(buffer, error, 1024); if (json == nullptr) { Com_Printf("Couldn't parse loading tips: %s\n", error); trap->TrueFree((void**)&buffer); return; } cJSON* child = cJSON_GetObjectItem(json, "tips"); if (child) { int arraySize = cJSON_GetArraySize(child); for (int i = 0; i < arraySize; i++) { cJSON* arrayItem = cJSON_GetArrayItem(child, i); loadingTip_t tip; Q_strncpyz(tip.tipText, cJSON_ToStringOpt(arrayItem, ""), sizeof(tip)); cg_loadingTips.push_back(tip); } } trap->TrueFree((void**)&buffer); // Display this tip cg_displayTipNumber = rand() % (cg_loadingTips.size() - 1); //cg_displayTipNumber = Q_irand(0, cg_loadingTips.size() - 1); }
/* ============================ JKG_ParseJetpackVisuals Parses the visual elements of a jetpack. FIXME: Should precache? ============================ */ static void JKG_ParseJetpackVisuals(cJSON* jsonNode, jetpackData_t& jetpackData) { cJSON* child; int boltSize; child = cJSON_GetObjectItem(jsonNode, "modelName"); Q_strncpyz(jetpackData.visuals.modelName, cJSON_ToStringOpt(child, ""), MAX_QPATH); child = cJSON_GetObjectItem(jsonNode, "effectBolts"); boltSize = cJSON_GetArraySize(child); for (int i = 0; i < boltSize; i++) { cJSON* arrayObj = cJSON_GetArrayItem(child, i); std::string bolt = cJSON_ToString(arrayObj); jetpackData.visuals.effectBolts.push_back(bolt); } child = cJSON_GetObjectItem(jsonNode, "hoverEffect"); Q_strncpyz(jetpackData.visuals.hoverEffect, cJSON_ToStringOpt(child, ""), MAX_QPATH); child = cJSON_GetObjectItem(jsonNode, "thrustEffect"); Q_strncpyz(jetpackData.visuals.thrustEffect, cJSON_ToStringOpt(child, ""), MAX_QPATH); child = cJSON_GetObjectItem(jsonNode, "jetEffect"); Q_strncpyz(jetpackData.visuals.jetEffect, cJSON_ToStringOpt(child, ""), MAX_QPATH); child = cJSON_GetObjectItem(jsonNode, "idleSound"); Q_strncpyz(jetpackData.visuals.idleSound, cJSON_ToStringOpt(child, ""), MAX_QPATH); child = cJSON_GetObjectItem(jsonNode, "thrustSound"); Q_strncpyz(jetpackData.visuals.thrustSound, cJSON_ToStringOpt(child, ""), MAX_QPATH); child = cJSON_GetObjectItem(jsonNode, "activateSound"); Q_strncpyz(jetpackData.visuals.activateSound, cJSON_ToStringOpt(child, ""), MAX_QPATH); child = cJSON_GetObjectItem(jsonNode, "deactivateSound"); Q_strncpyz(jetpackData.visuals.deactivateSound, cJSON_ToStringOpt(child, ""), MAX_QPATH); child = cJSON_GetObjectItem(jsonNode, "sputterSound"); Q_strncpyz(jetpackData.visuals.sputterSound, cJSON_ToStringOpt(child, ""), MAX_QPATH); }
static void BG_ParseAnimationObject ( cJSON *animationNode, int *torsoAnimation, int *legsAnimation ) { cJSON *node = cJSON_GetObjectItem (animationNode, "torso"); const char *anim = cJSON_ToStringOpt (node, "BOTH_STAND1"); *torsoAnimation = GetIDForString (animTable, anim); node = cJSON_GetObjectItem (animationNode, "legs"); if ( node == NULL ) { *legsAnimation = *torsoAnimation; return; } anim = cJSON_ToString (node); *legsAnimation = GetIDForString (animTable, anim); }
/* ===================== JKG_ParseArmorVisuals ===================== */ void JKG_ParseArmorVisuals(cJSON* json, armorData_t& armor) { char ghoul2Ref[MAX_QPATH] {0}; char ghoul2Model[MAX_QPATH]{0}; std::string ghoul2Surface; cJSON* jsonNode; cJSON* child; int count; // FIXME: is this really needed on the server? jsonNode = cJSON_GetObjectItem(json, "model"); Q_strncpyz(ghoul2Model, cJSON_ToStringOpt(jsonNode, ""), MAX_QPATH); jsonNode = cJSON_GetObjectItem(json, "modelGroup"); Q_strncpyz(ghoul2Ref, cJSON_ToStringOpt(jsonNode, ""), MAX_QPATH); if (ghoul2Ref[0]) { armor.visuals.pGHOUL2 = JKG_RegisterArmorGhoul2(ghoul2Ref, ghoul2Model); } jsonNode = cJSON_GetObjectItem(json, "motionBone"); Q_strncpyz(armor.visuals.motionBone, cJSON_ToStringOpt(jsonNode, ""), MAX_QPATH); // Handle surfaces to turn on/off. // These are handled as an array in the JSON file jsonNode = cJSON_GetObjectItem(json, "armorOnSurfaces"); if (jsonNode) { count = cJSON_GetArraySize(jsonNode); for (int i = 0; i < count; i++) { child = cJSON_GetArrayItem(jsonNode, i); ghoul2Surface = cJSON_ToStringOpt(child, ""); armor.visuals.armorOnSurfs.push_back(ghoul2Surface); } } jsonNode = cJSON_GetObjectItem(json, "bodyOffSurfaces"); if (jsonNode) { count = cJSON_GetArraySize(jsonNode); for (int i = 0; i < count; i++) { child = cJSON_GetArrayItem(jsonNode, i); ghoul2Surface = cJSON_ToStringOpt(child, ""); armor.visuals.bodyOffSurfs.push_back(ghoul2Surface); } } // The sound for equipping the piece jsonNode = cJSON_GetObjectItem(json, "equippedSound"); Q_strncpyz(armor.visuals.equipSound, cJSON_ToStringOpt(jsonNode, ""), MAX_QPATH); }
/* ===================== JKG_ParseArmorFile ===================== */ static qboolean JKG_ParseArmorFile(char* buffer, const char* fileName, armorData_t& armorData) { char errorBuffer[ARMOR_ERRBUFFER] {0}; cJSON* json; cJSON* jsonNode; json = cJSON_ParsePooled(buffer, errorBuffer, sizeof(errorBuffer)); if (json == nullptr) { Com_Printf(S_COLOR_RED "%s: %s\n", fileName, errorBuffer); return qfalse; } // Basic information jsonNode = cJSON_GetObjectItem(json, "ref"); if (!jsonNode) { Com_Printf(S_COLOR_RED "%s doesn't contain a valid ref name!\n", fileName); cJSON_Delete(json); return qfalse; } Q_strncpyz(armorData.ref, cJSON_ToString(jsonNode), sizeof(armorData.ref)); jsonNode = cJSON_GetObjectItem(json, "slot"); armorData.slot = JKG_ArmorSlotFromText(cJSON_ToStringOpt(jsonNode, "")); jsonNode = cJSON_GetObjectItem(json, "armor"); armorData.armor = cJSON_ToIntegerOpt(jsonNode, 0); jsonNode = cJSON_GetObjectItem(json, "hp"); armorData.hp = cJSON_ToIntegerOpt(jsonNode, 0); jsonNode = cJSON_GetObjectItem(json, "movemodifier"); armorData.movemodifier = cJSON_ToNumberOpt(jsonNode, 1.0); jsonNode = cJSON_GetObjectItem(json, "visuals"); JKG_ParseArmorVisuals(jsonNode, armorData); cJSON_Delete(json); return qtrue; }
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 void BG_ParseWeaponFireMode ( weaponFireModeStats_t *fireModeStats, cJSON *fireModeNode ) { cJSON *node; const char *str = NULL; if ( fireModeNode == NULL ) { return; } node = cJSON_GetObjectItem (fireModeNode, "ammo"); str = cJSON_ToString (node); if ( str && str[0] ) { fireModeStats->ammo = BG_GetAmmo (str); } node = cJSON_GetObjectItem (fireModeNode, "damage"); #ifdef QAGAME BG_ParseDamage (fireModeStats, node, qfalse); node = cJSON_GetObjectItem (fireModeNode, "secondarydamage"); BG_ParseDamage (fireModeStats, node, qtrue); #else fireModeStats->baseDamage = cJSON_ToInteger (node); #endif node = cJSON_GetObjectItem (fireModeNode, "grenade"); fireModeStats->isGrenade = (qboolean)cJSON_ToBooleanOpt (node, 0); node = cJSON_GetObjectItem (fireModeNode, "grenadeBounces"); fireModeStats->grenadeBounces = (qboolean)cJSON_ToBooleanOpt (node, 1); node = cJSON_GetObjectItem (fireModeNode, "grenadeBounceDMG"); fireModeStats->grenadeBounceDMG = (char)cJSON_ToIntegerOpt (node, 10); node = cJSON_GetObjectItem (fireModeNode, "ballistic"); fireModeStats->applyGravity = (char)cJSON_ToBooleanOpt (node, 0); node = cJSON_GetObjectItem (fireModeNode, "bounces"); fireModeStats->bounceCount = (char)cJSON_ToIntegerOpt (node, 0); node = cJSON_GetObjectItem (fireModeNode, "hitscan"); fireModeStats->hitscan = (char)cJSON_ToBooleanOpt (node, 0); node = cJSON_GetObjectItem (fireModeNode, "projectiles"); fireModeStats->shotCount = (char)cJSON_ToIntegerOpt (node, 0); node = cJSON_GetObjectItem (fireModeNode, "collisionsize"); fireModeStats->boxSize = (float)cJSON_ToNumberOpt (node, 0.0); node = cJSON_GetObjectItem (fireModeNode, "maxchargetime"); fireModeStats->chargeMaximum = (short)cJSON_ToIntegerOpt (node, 0); node = cJSON_GetObjectItem (fireModeNode, "chargedamage"); fireModeStats->chargeMultiplier = (float)cJSON_ToNumberOpt (node, 0); node = cJSON_GetObjectItem (fireModeNode, "chargedelay"); fireModeStats->chargeTime = (short)cJSON_ToIntegerOpt (node, 0); node = cJSON_GetObjectItem (fireModeNode, "ammocost"); fireModeStats->cost = (char)cJSON_ToIntegerOpt (node, 0); node = cJSON_GetObjectItem (fireModeNode, "firingtype"); BG_ParseFireModeFiringType (fireModeStats, cJSON_ToStringOpt (node, "auto")); // 0 means fully automatic, otherwise one burst will fire weapon n times. node = cJSON_GetObjectItem (fireModeNode, "shotsperburst"); fireModeStats->shotsPerBurst = (char)cJSON_ToIntegerOpt (node, 0); // 0 means infinite delay (semi-automatic), otherwise n milliseconds between // rounds in a burst. node = cJSON_GetObjectItem (fireModeNode, "burstshotdelay"); fireModeStats->burstFireDelay = (short)cJSON_ToIntegerOpt (node, 0); node = cJSON_GetObjectItem (fireModeNode, "firedelay"); fireModeStats->delay = (short)cJSON_ToIntegerOpt (node, 0); node = cJSON_GetObjectItem (fireModeNode, "range"); fireModeStats->range = (float)cJSON_ToIntegerOpt (node, WPR_M); node = cJSON_GetObjectItem (fireModeNode, "splashrange"); fireModeStats->rangeSplash = (float)cJSON_ToNumberOpt (node, 0.0); node = cJSON_GetObjectItem (fireModeNode, "recoil"); fireModeStats->recoil = (float)cJSON_ToNumberOpt (node, 0.0); //node = cJSON_GetObjectItem (fireModeNode, "spread"); //fireModeStats->spread = (float)cJSON_ToNumberOpt (node, 0.0); node = cJSON_GetObjectItem (fireModeNode, "accuracy"); if( node ) { cJSON *child = NULL; child = cJSON_GetObjectItem( node, "accuracyRating" ); fireModeStats->weaponAccuracy.accuracyRating = (vec_t)cJSON_ToNumberOpt( child, 32.0f ); child = cJSON_GetObjectItem( node, "crouchModifier" ); fireModeStats->weaponAccuracy.crouchModifier = (float)cJSON_ToNumberOpt( child, 0.8f ); child = cJSON_GetObjectItem( node, "runModifier" ); fireModeStats->weaponAccuracy.runModifier = (float)cJSON_ToNumberOpt( child, 2.0f ); child = cJSON_GetObjectItem( node, "sightsModifier" ); fireModeStats->weaponAccuracy.sightsModifier = (float)cJSON_ToNumberOpt( child, 0.2f ); child = cJSON_GetObjectItem( node, "walkModifier" ); fireModeStats->weaponAccuracy.walkModifier = (float)cJSON_ToNumberOpt( child, 1.55f ); child = cJSON_GetObjectItem( node, "inAirModifier" ); fireModeStats->weaponAccuracy.inAirModifier = (float)cJSON_ToNumberOpt( child, 3.0f ); child = cJSON_GetObjectItem( node, "accuracyRatingPerShot" ); fireModeStats->weaponAccuracy.accuracyRatingPerShot = (int)cJSON_ToNumberOpt( child, 2 ); child = cJSON_GetObjectItem( node, "msToDrainAccuracy" ); fireModeStats->weaponAccuracy.msToDrainAccuracy = (int)cJSON_ToNumberOpt( child, 200 ); child = cJSON_GetObjectItem( node, "maxAccuracyAdd" ); fireModeStats->weaponAccuracy.maxAccuracyAdd = (int)cJSON_ToNumberOpt( child, 128 ); } else { fireModeStats->weaponAccuracy.accuracyRating = 32.0f; fireModeStats->weaponAccuracy.crouchModifier = 0.8f; fireModeStats->weaponAccuracy.runModifier = 2.0f; fireModeStats->weaponAccuracy.sightsModifier = 0.2f; fireModeStats->weaponAccuracy.walkModifier = 1.55f; fireModeStats->weaponAccuracy.inAirModifier = 3.0f; fireModeStats->weaponAccuracy.accuracyRatingPerShot = 2; fireModeStats->weaponAccuracy.msToDrainAccuracy = 200; fireModeStats->weaponAccuracy.maxAccuracyAdd = 128; } node = cJSON_GetObjectItem (fireModeNode, "projectilespeed"); fireModeStats->speed = (float)cJSON_ToNumberOpt (node, 0.0); node = cJSON_GetObjectItem (fireModeNode, "projectileclass"); str = cJSON_ToStringOpt (node, "unknown_proj"); Q_strncpyz (fireModeStats->weaponClass, str, sizeof (fireModeStats->weaponClass)); node = cJSON_GetObjectItem (fireModeNode, "meansofdeath"); str = cJSON_ToStringOpt (node, "MOD_UNKNOWN"); fireModeStats->weaponMOD = GetIDForString (MODTable, str); node = cJSON_GetObjectItem (fireModeNode, "splashmeansofdeath"); str = cJSON_ToStringOpt (node, "MOD_UNKNOWN"); fireModeStats->weaponSplashMOD = GetIDForString (MODTable, str); }
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; } } }