public ExplosionPreset( ProtoObjectCharredGround protoObjectCharredGround, double serverDamageApplyDelay, TextureAtlasResource[] spriteAtlasResources, ReadOnlySoundResourceSet soundSet, Color?spriteColorAdditive, Color?spriteColorMultiplicative, double spriteBrightness, double spriteAnimationDuration, Size2F spriteSize, DrawOrder spriteDrawOrder, double blastwaveDelay, double blastwaveAnimationDuration, Color blastWaveColor, Size2F blastwaveSizeFrom, Size2F blastwaveSizeTo, double lightWorldSize, double lightDuration, Color lightColor, float screenShakesDuration, float screenShakesWorldDistanceMin, float screenShakesWorldDistanceMax, byte soundsCuesNumber) { this.ServerDamageApplyDelay = serverDamageApplyDelay; this.SpriteAtlasResources = spriteAtlasResources; this.SoundSet = soundSet; this.SpriteColorAdditive = spriteColorAdditive; this.SpriteColorMultiplicative = spriteColorMultiplicative ?? Colors.White; this.SpriteBrightness = (float)spriteBrightness; this.SpriteAnimationDuration = spriteAnimationDuration; this.SpriteSize = spriteSize; this.BlastwaveDelay = blastwaveDelay; this.BlastwaveAnimationDuration = blastwaveAnimationDuration; this.BlastWaveColor = blastWaveColor; this.BlastwaveSizeFrom = blastwaveSizeFrom; this.BlastwaveSizeTo = blastwaveSizeTo; this.LightWorldSize = lightWorldSize; this.LightDuration = lightDuration; this.LightColor = lightColor; this.ScreenShakesDuration = screenShakesDuration; this.ScreenShakesWorldDistanceMin = screenShakesWorldDistanceMin; this.ScreenShakesWorldDistanceMax = screenShakesWorldDistanceMax; this.SoundsCuesNumber = soundsCuesNumber; this.SpriteDrawOrder = spriteDrawOrder; this.ProtoObjectCharredGround = protoObjectCharredGround; if (this.SoundSet.Count == 0) { Api.Logger.Warning("No sounds in the explosion sounds preset - please check the sounds path"); } }
// helper method to create and setup the explosion preset public static ExplosionPreset CreatePreset( ProtoObjectCharredGround protoObjectCharredGround, double serverDamageApplyDelay, string soundSetPath, double spriteAnimationDuration, string spriteSetPath, byte spriteAtlasColumns, byte spriteAtlasRows, Size2F spriteWorldSize, double blastwaveDelay, double blastwaveAnimationDuration, Color blastWaveColor, Size2F blastwaveWorldSizeFrom, Size2F blastwaveWorldSizeTo, double lightDuration, double lightWorldSize, Color lightColor, double screenShakesDuration, double screenShakesWorldDistanceMin, double screenShakesWorldDistanceMax, Color?spriteColorAdditive = null, Color?spriteColorMultiplicative = null, double spriteBrightness = 1, DrawOrder spriteDrawOrder = DrawOrder.Explosion, byte soundsCuesNumber = 17) { var sounds = new SoundResourceSet() .Add(soundSetPath) .ToReadOnly(); using var tempFilePaths = Api.Shared.FindFilesWithTrailingNumbers( ContentPaths.Textures + spriteSetPath); var filePaths = tempFilePaths.AsList(); if (filePaths.Count == 0) { Api.Logger.Error("The explosion preset is empty - no explosion textures found at " + spriteSetPath); } var spriteAtlasResources = new TextureAtlasResource[filePaths.Count]; for (var index = 0; index < filePaths.Count; index++) { var filePath = filePaths[index]; spriteAtlasResources[index] = new TextureAtlasResource(filePath, spriteAtlasColumns, spriteAtlasRows, isTransparent: true); } return(new ExplosionPreset(protoObjectCharredGround, serverDamageApplyDelay, spriteAtlasResources, sounds, spriteColorAdditive, spriteColorMultiplicative, spriteBrightness, spriteAnimationDuration, spriteWorldSize * ScriptingConstants.TileSizeRealPixels, spriteDrawOrder, blastwaveDelay, blastwaveAnimationDuration, blastWaveColor, blastwaveWorldSizeFrom * ScriptingConstants.TileSizeRealPixels, blastwaveWorldSizeTo * ScriptingConstants.TileSizeRealPixels, lightWorldSize, lightDuration, lightColor, (float)screenShakesDuration, (float)screenShakesWorldDistanceMin, (float)screenShakesWorldDistanceMax, soundsCuesNumber)); }
public static void ServerExplode( [CanBeNull] ICharacter character, [CanBeNull] IProtoExplosive protoExplosive, [CanBeNull] IProtoItemWeapon protoWeapon, ExplosionPreset explosionPreset, Vector2D epicenterPosition, DamageDescription damageDescriptionCharacters, IPhysicsSpace physicsSpace, ExecuteExplosionDelegate executeExplosionCallback) { ValidateIsServer(); // schedule explosion charred ground spawning var protoObjectCharredGround = explosionPreset.ProtoObjectCharredGround; if (protoObjectCharredGround is not null) { ServerTimersSystem.AddAction( delaySeconds: explosionPreset.SpriteAnimationDuration * 0.5, () => { var tilePosition = (Vector2Ushort)(epicenterPosition - protoObjectCharredGround.Layout.Center); var canSpawnCharredGround = true; var tile = Server.World.GetTile(tilePosition); if (tile.ProtoTile.Kind != TileKind.Solid || tile.EightNeighborTiles.Any(t => t.ProtoTile.Kind != TileKind.Solid)) { // allow charred ground only on solid ground canSpawnCharredGround = false; } if (canSpawnCharredGround) { // remove existing charred ground objects at the same tile foreach (var staticWorldObject in Shared.WrapInTempList( tile.StaticObjects) .EnumerateAndDispose()) { switch (staticWorldObject.ProtoStaticWorldObject) { case ProtoObjectCharredGround _: Server.World.DestroyObject(staticWorldObject); break; case IProtoObjectDeposit _: // don't show charred ground over resource deposits (it looks wrong) canSpawnCharredGround = false; break; } } } if (canSpawnCharredGround && PveSystem.ServerIsPvE) { var bounds = protoObjectCharredGround.Layout.Bounds; if (LandClaimSystem.SharedIsLandClaimedByAnyone( new RectangleInt(tilePosition, bounds.Size + (1, 1)))) { // ensure that it's not possible to create charred ground in a land claim area in PvE canSpawnCharredGround = false; } } if (canSpawnCharredGround) { // spawn charred ground var objectCharredGround = Server.World.CreateStaticWorldObject(protoObjectCharredGround, tilePosition); var objectCharredGroundOffset = epicenterPosition - tilePosition.ToVector2D(); if (objectCharredGroundOffset != Vector2D.Zero) { ProtoObjectCharredGround.ServerSetWorldOffset(objectCharredGround, (Vector2F)objectCharredGroundOffset); } } }); } // schedule explosion damage ServerTimersSystem.AddAction( delaySeconds: explosionPreset.ServerDamageApplyDelay, () => { // prepare weapon caches var characterFinalStatsCache = character?.SharedGetFinalStatsCache() ?? FinalStatsCache.Empty; var weaponFinalCache = new WeaponFinalCache(character, characterFinalStatsCache, weapon: null, protoWeapon: protoWeapon, protoAmmo: null, damageDescription: damageDescriptionCharacters, protoExplosive: protoExplosive); // execute explosion executeExplosionCallback( positionEpicenter: epicenterPosition, physicsSpace: physicsSpace, weaponFinalCache: weaponFinalCache); }); }