public void Throw(Vector3 pos, Map map, Thing instigator, float scaleFactor = 1) { if (!PropsCE.fragments.NullOrEmpty()) { if (map == null) { Log.Warning("CombatExtended :: Tried to throw fragments in a null map."); return; } if (!pos.ToIntVec3().InBounds(map)) { Log.Warning("CombatExtended :: Tried to throw fragments out of bounds"); return; } var projCE = parent as ProjectileCE; var edifice = pos.ToIntVec3().GetEdifice(map); var edificeHeight = edifice == null ? 0f : new CollisionVertical(edifice).Max; var height = projCE != null?Mathf.Max(edificeHeight, projCE.Height) : edificeHeight; foreach (var fragment in PropsCE.fragments) { var newCount = fragment; newCount.count = Mathf.RoundToInt(newCount.count * scaleFactor); _monoDummy.GetComponent <MonoDummy>().StartCoroutine(FragRoutine(pos, map, height, instigator, fragment, PropsCE.fragSpeedFactor)); } } }
/// <summary> /// Produces a secondary explosion on impact using the explosion values from the projectile's projectile def. Requires the projectile's launcher to be passed on due to protection level. /// Intended use is for HEAT and similar weapons that spawn secondary explosions while also penetrating, NOT explosive ammo of anti-materiel rifles as the explosion just spawns /// on top of the pawn, not inside the hit body part. /// /// Additionally handles fragmentation effects if defined. /// </summary> /// <param name="instigator">Launcher of the projectile calling the method</param> public virtual void Explode(Thing instigator, Vector3 pos, Map map, float scaleFactor = 1) { var posIV = pos.ToIntVec3(); if (map == null) { Log.Warning("Tried to do explodeCE in a null map."); return; } if (!posIV.InBounds(map)) { Log.Warning("Tried to explodeCE out of bounds"); return; } if (!Props.fragments.NullOrEmpty()) { var projCE = parent as ProjectileCE; var edifice = posIV.GetEdifice(map); var edificeHeight = edifice == null ? 0 : new CollisionVertical(edifice).Max; var height = projCE != null?Mathf.Max(edificeHeight, pos.y) : edificeHeight; foreach (var fragment in Props.fragments) { _monoDummy.GetComponent <MonoDummy>().StartCoroutine(FragRoutine(pos, map, height, instigator, fragment, Props.fragSpeedFactor)); } } // Regular explosion stuff if (Props.explosionRadius > 0 && Props.explosionDamage > 0 && parent.def != null && GenGrid.InBounds(posIV, map)) { // Copy-paste from GenExplosion ExplosionCE explosion = GenSpawn.Spawn(CE_ThingDefOf.ExplosionCE, posIV, map) as ExplosionCE; explosion.height = pos.y; explosion.radius = Props.explosionRadius * scaleFactor; explosion.damType = Props.explosionDamageDef; explosion.instigator = instigator; explosion.damAmount = GenMath.RoundRandom(Props.explosionDamage * scaleFactor); explosion.weapon = null; explosion.projectile = parent.def; explosion.preExplosionSpawnThingDef = Props.preExplosionSpawnThingDef; explosion.preExplosionSpawnChance = Props.preExplosionSpawnChance; explosion.preExplosionSpawnThingCount = Props.preExplosionSpawnThingCount; explosion.postExplosionSpawnThingDef = Props.postExplosionSpawnThingDef; explosion.postExplosionSpawnChance = Props.postExplosionSpawnChance; explosion.postExplosionSpawnThingCount = Props.postExplosionSpawnThingCount; explosion.applyDamageToExplosionCellsNeighbors = Props.applyDamageToExplosionCellsNeighbors; explosion.armorPenetration = explosion.damAmount * 0.1f; explosion.damageFalloff = Props.damageFalloff; explosion.chanceToStartFire = Props.chanceToStartFire; explosion.StartExplosion(Props.soundExplode ?? Props.explosionDamageDef.soundExplosion); } }