/* ============================ 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; }
//========================================================= // 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_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 int GLua_JSON_ToIntegerOpt( 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_pushinteger( L, cJSON_ToIntegerOpt( node, luaL_checkinteger( L, 2 ) ) ); return 1; }
/* ============================ JKG_ParseJetpack Parses a jetpack file, from memory. ============================ */ static qboolean JKG_ParseJetpack(char* buffer, const char* fileName, jetpackData_t& jetpackData) { char errorBuffer[JETPACK_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(jetpackData.ref, cJSON_ToString(jsonNode), sizeof(jetpackData.ref)); jsonNode = cJSON_GetObjectItem(json, "fuelCapacity"); jetpackData.fuelCapacity = cJSON_ToIntegerOpt(jsonNode, 100); jsonNode = cJSON_GetObjectItem(json, "fuelConsumption"); jetpackData.fuelConsumption = cJSON_ToNumberOpt(jsonNode, 1.0); jsonNode = cJSON_GetObjectItem(json, "thrustConsumption"); jetpackData.thrustConsumption = cJSON_ToNumberOpt(jsonNode, 2.0); jsonNode = cJSON_GetObjectItem(json, "fuelRegeneration"); jetpackData.fuelRegeneration = cJSON_ToNumberOpt(jsonNode, 1.0); // Movement related fields jsonNode = cJSON_GetObjectItem(json, "movement"); JKG_ParseJetpackMovement(jsonNode, jetpackData); // Visuals jsonNode = cJSON_GetObjectItem(json, "visuals"); JKG_ParseJetpackVisuals(jsonNode, jetpackData); cJSON_Delete(json); return qtrue; }
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; } } }