public static float CalculateMuzzleVelocity( ProjectileData projectile, float propellantMass, ExplosiveReaction propellantReaction, float barrelLength, float staticFrictionalCoefficient, float dynamicFrictionalCoefficient, float simulationTickDelta = 0.00001f, int maxSimulationSamples = 1000 ) { float projectileVelocity = 0.0f, projectileDistance = 0.0f, pressure = 0.0f, elapsedTime = 0.0f, barrelVolume = Mathf.PI * projectile.CrossSectionalArea; //V=M/D int numberOfGranules = (int)( (propellantMass * propellantReaction.density) //Propellant volume / propellantReaction.boundingBoxVolume); //Volume per granule //How many granules of propellant do we have? for (int i = 0; i < maxSimulationSamples; i++) { //Build up pressure from the propellant pressure += (propellantReaction.GetReleasedGasTimeSegment (elapsedTime, simulationTickDelta) * numberOfGranules)//Volume of released gas ; if (projectileVelocity == 0.0f) //Use static friction { } else //Use dynamic friction { } projectileDistance += projectileVelocity * simulationTickDelta; elapsedTime += simulationTickDelta; } //{TODO} Continue! return(0.0f); }
void CreateExplosion(ExplosiveReaction reaction, FreeReactant reactant1, FreeReactant reactant2) { double reactantRatio = reaction.reactantRatios[reactant1.resource.id] / reaction.reactantRatios[reactant2.resource.id]; double reactant1Amount = reactant1.resourceMass; double reactant2Amount = reactant2.resourceMass; double fuelOxRatio = reactant2Amount * reactantRatio / reactant1Amount; if (fuelOxRatio > 1) //means there is more reactant 2 than is needed { reactant2Amount = reactant1Amount / reactantRatio; //amount of reactant2 needed for reaction reactant1.resourceMass -= reactant1Amount; //remove this from FreeReactant reactant2.resourceMass -= reactant2Amount; } else { reactant1Amount = reactant2Amount * reactantRatio; //amount of reactant2 needed for reaction reactant1.resourceMass -= reactant1Amount; //remove this from FreeReactant reactant2.resourceMass -= reactant2Amount; } Vector3d avgVel = reactant1.worldVelocity * reactant1Amount + reactant2.worldVelocity * reactant2Amount; avgVel /= reactant1Amount + reactant2Amount; double fractionTNTEquivalent = reaction.PYROYieldCurve.Evaluate((float)avgVel.magnitude) * 4.184e6 * (reactant1Amount + reactant2Amount); Vector3d avgPos = reactant1.worldPosition * reactant1Amount + reactant2.worldPosition * reactant2Amount; avgPos /= reactant1Amount + reactant2Amount; Debug.Log("[Blastwave]: Create Explosion with yield of " + fractionTNTEquivalent + " J"); //create blastwave Blastwave.CreateBlastwave((float)fractionTNTEquivalent, reaction.maxOverPreskPa, reaction.impulseFactor, avgPos); //create fireball //TODO fireball call }
void RunAllReactions() { for (int i = 0; i < freeReactants.Count; ++i) { FreeReactant reactantI = freeReactants[i]; Vector3d reactantIPos = reactantI.worldPosition; double reactantIRad = reactantI.effectiveRadius; if (reactantI.resourceMass <= 0) { continue; } for (int j = i + 1; j < freeReactants.Count; ++j) { if (i == j) { continue; } FreeReactant reactantJ = freeReactants[j]; if (reactantI.resource.id == reactantJ.resource.id) { continue; } if (reactantJ.resourceMass <= 0) { continue; } if ((reactantIPos - reactantJ.worldPosition).magnitude > (reactantIRad + reactantJ.effectiveRadius) * 0.9) { continue; } HashSet <ExplosiveReaction> iReactionSet = reactantPotentialReactions[reactantI.resource.id]; HashSet <ExplosiveReaction> jReactionSet = reactantPotentialReactions[reactantJ.resource.id]; ExplosiveReaction thisReaction = null; if (iReactionSet.Count > jReactionSet.Count) { foreach (ExplosiveReaction e in jReactionSet) { if (iReactionSet.Contains(e)) { thisReaction = e; break; } } } else { foreach (ExplosiveReaction e in iReactionSet) { if (jReactionSet.Contains(e)) { thisReaction = e; break; } } } if (thisReaction != null) { CreateExplosion(thisReaction, reactantI, reactantJ); } } } }
void AddExplosiveReactionToDict(ConfigNode explosiveNode) { if (explosiveNode == null) { return; } PartResourceDefinitionList resourceDefinitions = PartResourceLibrary.Instance.resourceDefinitions; ExplosiveReaction reaction = new ExplosiveReaction(); if (explosiveNode.HasValue("requiresOxygenAtm")) { bool.TryParse(explosiveNode.GetValue("requiresOxygenAtm"), out reaction.requiresOxygenAtm); } if (explosiveNode.HasValue("maxOverPreskPa")) { float.TryParse(explosiveNode.GetValue("maxOverPreskPa"), out reaction.maxOverPreskPa); } if (explosiveNode.HasValue("impulseFactor")) { float.TryParse(explosiveNode.GetValue("impulseFactor"), out reaction.impulseFactor); } if (explosiveNode.HasNode("PYROYieldCurve")) { reaction.PYROYieldCurve = new FloatCurve(); reaction.PYROYieldCurve.Load(explosiveNode.GetNode("PYROYieldCurve")); } if (explosiveNode.HasValue("resource")) { string[] vals = explosiveNode.GetValues("resource"); for (int j = 0; j < vals.Length; ++j) { string[] splitStr = vals[j].Split(new char[] { ',', ' ' }); PartResourceDefinition res = null; double resRatio = 0; for (int i = 0; i < splitStr.Length; ++i) { if (splitStr[i].Length <= 0) { continue; } if (res == null && resourceDefinitions.Contains(splitStr[i])) { res = resourceDefinitions[splitStr[i]]; continue; } else { if (double.TryParse(splitStr[i], out resRatio)) { break; } } } if (res == null && resRatio <= 0) { Debug.LogError("[Blastwave]: Couldn't find resource for reaction"); continue; } reaction.reactantRatios.Add(res.id, resRatio); reactantPotentialReactions[res.id].Add(reaction); } } }