public static void ParseEffectDefinition(VehicleEffectsDefinition.Vehicle vehicleDef, VehicleEffectsDefinition.Effect effectDef, List <VehicleInfo.Effect> effectsList, ref HashSet <string> parseErrors) { if (effectDef?.Name == null) { parseErrors.Add(vehicleDef.Name + " - Effect name missing."); return; } string effectName = (effectDef.Replacment == null) ? effectDef.Name : effectDef.Replacment; effectName += (effectDef.Base != null) ? " - " + effectDef.Base : ""; var effectPrefab = FindEffect(effectName); if (effectPrefab == null) { //This effect is either a 'special' effect or simply non existent if (effectName.StartsWith("Vehicle Effect Wrapper")) { // Wrapper for effects if (effectDef.Base != null) { var baseEffect = FindEffect(effectDef.Base); if (baseEffect != null) { effectPrefab = CustomVehicleEffect.CreateEffect(effectDef, baseEffect); if (effectPrefab == null) { parseErrors.Add(vehicleDef.Name + ": An error occured trying to create a custom effect. Check debug log for details."); return; } } else { // Try fallback if (effectDef.Fallback != null) { Logging.Log(vehicleDef.Name + ": trying to use fallback " + effectDef.Fallback + " for " + effectName); if (effectDef.Fallback.StartsWith("None")) { // None specified as fallback, just exit return; } else if (effectDef.Fallback.StartsWith("Remove") && effectDef.Replacment != null) { // Remove the existing effect effectName = "Remove"; effectPrefab = null; } else { baseEffect = FindEffect(effectDef.Fallback); if (baseEffect != null) { effectPrefab = CustomVehicleEffect.CreateEffect(effectDef, baseEffect); if (effectPrefab == null) { parseErrors.Add(vehicleDef.Name + ": An error occured trying to create a custom effect. Check debug log for details."); return; } } else { parseErrors.Add(vehicleDef.Name + ": Vehicle Effect Wrapper fallback " + effectDef.Fallback + " was needed for " + effectDef.Base + " but not loaded either!"); } } } else { parseErrors.Add(vehicleDef.Name + ": Vehicle Effect Wrapper base effect " + effectDef.Base + " was not loaded and no fallback was specified!"); return; } } } else { parseErrors.Add(vehicleDef.Name + ": Vehicle Effect Wrapper requires a base effect but it wasn't given"); return; } } else if (effectName.StartsWith("Vehicle Effect Multi")) { // Custom MultiEffect defined in the xml if (effectDef.SubEffects != null) { List <MultiEffect.SubEffect> loadedSubEffects = new List <MultiEffect.SubEffect>(); foreach (var subEffect in effectDef.SubEffects) { var dummyList = new List <VehicleInfo.Effect>(); ParseEffectDefinition(vehicleDef, subEffect.Effect, dummyList, ref parseErrors); if (dummyList.Count > 0) { loadedSubEffects.Add(new MultiEffect.SubEffect() { m_effect = dummyList[0].m_effect, m_endTime = subEffect.EndTime, m_startTime = subEffect.StartTime, m_probability = subEffect.Probability }); } } effectPrefab = CustomVehicleMultiEffect.CreateEffect(effectDef, loadedSubEffects.ToArray(), effectDef.Duration, effectDef.UseSimulationTime); } else { parseErrors.Add(vehicleDef.Name + " Vehicle Effect Multi with no sub effects!"); return; } } else if (effectName.StartsWith("None") || effectName.StartsWith("Remove")) { // Not a real effect, but keywords used for removal of an existing effect. // 'None' included for < 1.2c compatibility effectName = "Remove"; effectPrefab = null; } else { // Try fallback if (effectDef.Fallback != null) { Logging.Log(vehicleDef.Name + ": trying to use fallback " + effectDef.Fallback + " for " + effectName); if (effectDef.Fallback.StartsWith("None")) { // None specified as fallback, just exit return; } else if (effectDef.Fallback.StartsWith("Remove") && effectDef.Replacment != null) { // Remove the existing effect effectName = "Remove"; effectPrefab = null; } else { effectPrefab = FindEffect(effectDef.Fallback); if (effectPrefab == null) { parseErrors.Add(vehicleDef.Name + " requested non-existing effect " + effectName + " and fallback " + effectDef.Fallback + " could not be found either!"); return; } } } else { parseErrors.Add(vehicleDef.Name + " requested non-existing effect " + effectName + " and no fallback was specified"); return; } } } if (effectPrefab == null && !effectName.Equals("Remove")) { parseErrors.Add(vehicleDef.Name + " - Effect with name " + effectDef.Name + " not loaded."); return; } var vehicleInfoEffect = new VehicleInfo.Effect { m_effect = effectPrefab, m_parkedFlagsForbidden = VehicleParked.Flags.Created, m_parkedFlagsRequired = VehicleParked.Flags.None, m_vehicleFlagsForbidden = (Vehicle.Flags)effectDef.ForbiddenFlags, m_vehicleFlagsRequired = ((Vehicle.Flags)effectDef.RequiredFlags) | Vehicle.Flags.Created }; if (effectDef.Replacment == null) { effectsList.Add(vehicleInfoEffect); } else { int indexToRemove = -1; for (int i = 0; i < effectsList.Count; i++) { if (effectsList[i].m_effect.name.Equals(effectDef.Name)) { if (effectDef.Replacment.Equals("Remove")) { indexToRemove = i; break; } effectsList[i] = vehicleInfoEffect; break; } } if (indexToRemove >= 0) { effectsList.RemoveAt(indexToRemove); } } }
/// <summary> /// Applies a vehicle definition vehicle entry. /// </summary> /// <param name="vehicleDef">Vehicle definition to parse.</param> /// <param name="packageName">Package name used in error messages.</param> /// <param name="backup">Used to store original effect array.</param> /// <param name="parseErrors">HashSet to add parse errors to.</param> /// <param name="noParseErrors">Optional: If true no vehicle related parse errors are given.</param> /// <param name="vehicleDefPrefab">Optional: VehicleInfo to apply definition to.</param> public static void ParseVehicleDefinition(VehicleEffectsDefinition.Vehicle vehicleDef, string packageName, ref Dictionary <VehicleInfo, VehicleInfo.Effect[]> backup, ref HashSet <string> parseErrors, bool noParseErrors = false, VehicleInfo vehicleDefPrefab = null) { if (vehicleDef?.Name == null) { if (!noParseErrors) { parseErrors.Add(packageName + " - Vehicle name missing."); } return; } if (vehicleDefPrefab == null) { vehicleDefPrefab = FindVehicle(vehicleDef.Name, packageName); } if (vehicleDefPrefab == null) { if (!noParseErrors) { parseErrors.Add(packageName + " - Vehicle with name " + vehicleDef.Name + " not loaded."); } return; } if (vehicleDef.Effects == null || vehicleDef.Effects.Count == 0) { if (!noParseErrors) { parseErrors.Add(packageName + " - No effects specified for " + vehicleDef.Name + "."); } return; } if (vehicleDef.ApplyToTrailersOnly) { HashSet <VehicleInfo> trailers = new HashSet <VehicleInfo>(); foreach (var trailer in vehicleDefPrefab.m_trailers) { if (!trailers.Contains(trailer.m_info)) { trailers.Add(trailer.m_info); } } foreach (var trailer in trailers) { var trailerDef = new VehicleEffectsDefinition.Vehicle(); trailerDef.Name = trailer.name; trailerDef.Effects = vehicleDef.Effects; ParseVehicleDefinition(trailerDef, packageName, ref backup, ref parseErrors, noParseErrors, trailer); } return; } // Backup default effects array if (!backup.ContainsKey(vehicleDefPrefab)) { var effects = new VehicleInfo.Effect[vehicleDefPrefab.m_effects.Length]; vehicleDefPrefab.m_effects.CopyTo(effects, 0); backup.Add(vehicleDefPrefab, effects); } var vehicleEffectsList = new List <VehicleInfo.Effect>(); vehicleEffectsList.AddRange(vehicleDefPrefab.m_effects); foreach (var effectDef in vehicleDef.Effects) { ParseEffectDefinition(vehicleDef, effectDef, vehicleEffectsList, ref parseErrors); } // Remove and log null effects for (int i = vehicleEffectsList.Count - 1; i >= 0; i--) { if (vehicleEffectsList[i].m_effect == null) { Logging.LogWarning("Found effect that is NULL for vehicle " + vehicleDef.Name + " at index " + i + ", removing."); vehicleEffectsList.RemoveAt(i); } } // Update the VehicleInfo with the new effects vehicleDefPrefab.m_effects = vehicleEffectsList.ToArray(); // taken from VehicleInfo.InitializePrefab if (vehicleDefPrefab.m_effects != null) { for (int j = 0; j < vehicleDefPrefab.m_effects.Length; j++) { if (vehicleDefPrefab.m_effects[j].m_effect != null) { vehicleDefPrefab.m_effects[j].m_effect.InitializeEffect(); } } } }