//========================================================= // 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; }
/* ============================ 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; }
/* ============================ JKG_ParseJetpackMovement Parses the "movement" block of a jetpack. ============================ */ static void JKG_ParseJetpackMovement(cJSON* jsonNode, jetpackData_t& jetpackData) { cJSON* child; child = cJSON_GetObjectItem(jsonNode, "thrustAllowed"); jetpackData.move.thrustAllowed = cJSON_ToBooleanOpt(child, true); child = cJSON_GetObjectItem(jsonNode, "fwdThrustAllowed"); jetpackData.move.fwdThrustAllowed = cJSON_ToBooleanOpt(child, true); child = cJSON_GetObjectItem(jsonNode, "loadBearingAllowed"); jetpackData.move.loadBearingAllowed = cJSON_ToBooleanOpt(child, false); child = cJSON_GetObjectItem(jsonNode, "hoverGravity"); jetpackData.move.hoverGravity = cJSON_ToNumberOpt(child, -1.0); child = cJSON_GetObjectItem(jsonNode, "forwardMove"); jetpackData.move.forwardMove = cJSON_ToNumberOpt(child, 1.0); child = cJSON_GetObjectItem(jsonNode, "backMove"); jetpackData.move.backMove = cJSON_ToNumberOpt(child, 1.0); child = cJSON_GetObjectItem(jsonNode, "sideMove"); jetpackData.move.sideMove = cJSON_ToNumberOpt(child, 1.0); child = cJSON_GetObjectItem(jsonNode, "downMove"); jetpackData.move.downMove = cJSON_ToNumberOpt(child, 1.0); child = cJSON_GetObjectItem(jsonNode, "thrustFwd"); jetpackData.move.thrustFwd = cJSON_ToNumberOpt(child, 1.0); child = cJSON_GetObjectItem(jsonNode, "thrustBack"); jetpackData.move.thrustBack = cJSON_ToNumberOpt(child, 1.0); child = cJSON_GetObjectItem(jsonNode, "thrustSide"); jetpackData.move.thrustSide = cJSON_ToNumberOpt(child, 1.0); child = cJSON_GetObjectItem(jsonNode, "thrustUp"); jetpackData.move.thrustUp = cJSON_ToNumberOpt(child, 1.0); child = cJSON_GetObjectItem(jsonNode, "fwdThrustAmt"); jetpackData.move.fwdThrustAmt = cJSON_ToNumberOpt(child, 2.0); }
static int GLua_JSON_ToNumberOpt( 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_pushnumber( L, cJSON_ToNumberOpt( node, luaL_checknumber( L, 2 ) ) ); return 1; }
/* ===================== 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 BG_ParseVisuals ( weaponData_t *weaponData, cJSON *visualsNode ) { cJSON *node = NULL; cJSON *child = NULL; weaponVisual_t *weaponVisuals = &weaponData->visuals; int i; ReadString (visualsNode, "worldmodel", weaponVisuals->world_model, sizeof (weaponVisuals->world_model)); ReadString (visualsNode, "viewmodel", weaponVisuals->view_model, sizeof (weaponVisuals->view_model)); ReadString (visualsNode, "hudicon", weaponVisuals->icon, sizeof (weaponVisuals->icon)); ReadString (visualsNode, "hudnaicon", weaponVisuals->icon_na, sizeof (weaponVisuals->icon_na)); ReadString (visualsNode, "selectsound", weaponVisuals->selectSound, sizeof (weaponVisuals->selectSound)); child = cJSON_GetObjectItem (visualsNode, "indicators"); if ( child ) { int numGroupIndicators = 0; int i; char *shaders[3]; cJSON *subchild = cJSON_GetObjectItem (child, "ammo"); if ( subchild ) { weaponVisuals->indicatorType = IND_NORMAL; numGroupIndicators = cJSON_ReadStringArray (subchild, 3, const_cast<const char **>(shaders)); for ( i = 0; i < numGroupIndicators; i++ ) { Q_strncpyz (weaponVisuals->groupedIndicatorShaders[i], shaders[i], sizeof (weaponVisuals->groupedIndicatorShaders[i])); } } else if ( (subchild = cJSON_GetObjectItem (child, "leds")) != NULL ) { weaponVisuals->indicatorType = IND_GRENADE; numGroupIndicators = cJSON_ReadStringArray (subchild, 3, const_cast<const char **>(shaders)); for ( i = 0; i < numGroupIndicators; i++ ) { Q_strncpyz (weaponVisuals->groupedIndicatorShaders[i], shaders[i], sizeof (weaponVisuals->groupedIndicatorShaders[i])); } } ReadString (child, "firemode", weaponVisuals->firemodeIndicatorShader, sizeof (weaponVisuals->firemodeIndicatorShader)); } ReadString (visualsNode, "gunposition", weaponVisuals->gunPosition, sizeof (weaponVisuals->gunPosition)); ReadString (visualsNode, "ironsightsPosition", weaponVisuals->ironsightsPosition, sizeof (weaponVisuals->ironsightsPosition)); node = cJSON_GetObjectItem (visualsNode, "ironsightsFov"); weaponVisuals->ironsightsFov = (float)cJSON_ToNumberOpt (node, 0.0); // Scope toggle child = cJSON_GetObjectItem (visualsNode, "scope"); ReadString (child, "startsound", weaponVisuals->scopeStartSound, sizeof (weaponVisuals->scopeStartSound)); ReadString (child, "stopsound", weaponVisuals->scopeStopSound, sizeof (weaponVisuals->scopeStopSound)); // Scope zoom node = cJSON_GetObjectItem (child, "looptime"); weaponVisuals->scopeSoundLoopTime = cJSON_ToInteger (node); ReadString (child, "loopsound", weaponVisuals->scopeLoopSound, sizeof (weaponVisuals->scopeLoopSound)); // Scope render ReadString (child, "mask", weaponVisuals->scopeShader, sizeof (weaponVisuals->scopeShader)); //Crosshair -- eezstreet add node = cJSON_GetObjectItem (visualsNode, "crosshairValue"); weaponVisuals->crosshairValue = (int)cJSON_ToNumberOpt(node, (double)1); /*node = cJSON_GetObjectItem (visualsNode, "primary"); BG_ParseVisualsFireMode (&weaponVisuals->primary, node); node = cJSON_GetObjectItem (visualsNode, "secondary"); BG_ParseVisualsFireMode (&weaponVisuals->secondary, node);*/ for ( i = 0; i < weaponData->numFiringModes; i++ ) { node = cJSON_GetObjectItem (visualsNode, va("firemode%i", i) ); if(node) { BG_ParseVisualsFireMode(&weaponVisuals->visualFireModes[i], node, weaponData->numFiringModes); } } }
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); }