private void ClientRemote_OnExplosion( Vector2D explosionWorldPosition) { var protoBomb = ProtoObjectBomb; SharedExplosionHelper.ClientExplode(explosionWorldPosition, protoBomb.ExplosionPreset, protoBomb.VolumeExplosion); }
protected virtual void ClientExplodeAt( IProtoItemWeapon protoWeapon, Vector2D shotSourcePosition, Vector2D explosionWorldPosition) { var timeToHit = WeaponSystemClientDisplay.SharedCalculateTimeToHit(protoWeapon.FireTracePreset ?? this.FireTracePreset, shotSourcePosition, explosionWorldPosition); ClientTimersSystem.AddAction(timeToHit, () => SharedExplosionHelper.ClientExplode(explosionWorldPosition, this.ExplosionPreset, this.VolumeExplosion)); }
protected override void ClientExplodeAt( IProtoItemWeapon protoWeapon, Vector2D shotSourcePosition, Vector2D explosionWorldPosition) { var timeToHit = WeaponSystemClientDisplay.SharedCalculateTimeToHit(protoWeapon.FireTracePreset ?? this.FireTracePreset, shotSourcePosition, explosionWorldPosition); ClientTimersSystem.AddAction( timeToHit, () => { SharedExplosionHelper.ClientExplode(explosionWorldPosition, this.ExplosionPreset, this.VolumeExplosion); // add more explosions in the X pattern as it's a fragmentation grenade ClientTimersSystem.AddAction( 0.2, () => { SharedExplosionHelper.ClientExplode(explosionWorldPosition + (1, 1), this.ExplosionPreset, volume: 0); SharedExplosionHelper.ClientExplode(explosionWorldPosition + (1, -1), this.ExplosionPreset, volume: 0); SharedExplosionHelper.ClientExplode(explosionWorldPosition + (-1, 1), this.ExplosionPreset, volume: 0); SharedExplosionHelper.ClientExplode(explosionWorldPosition + (-1, -1), this.ExplosionPreset, volume: 0); });
private void ServerExplodeAt(WeaponFinalCache weaponCache, Vector2D endPosition, bool isHit) { var character = weaponCache.Character; var protoWeapon = (IProtoItemWeaponRanged)weaponCache.ProtoWeapon; var shotSourcePosition = WeaponSystemClientDisplay.SharedCalculateWeaponShotWorldPositon( character, protoWeapon, character.ProtoCharacter, character.Position, hasTrace: true); if (isHit) { // offset end position a bit towards the source position // this way the explosion will definitely happen outside the hit object endPosition -= 0.1 * (endPosition - shotSourcePosition).Normalized; } var timeToHit = WeaponSystemClientDisplay.SharedCalculateTimeToHit( protoWeapon.FireTracePreset ?? this.FireTracePreset, shotSourcePosition, endPosition); // We're using a check here similar to the one in WeaponSystem. // Ensure that player can hit objects only on the same height level // and can fire through over the pits (the cliffs of the lower heights). var anyCliffIsAnObstacle = character.Tile.Height != Server.World.GetTile(endPosition.ToVector2Ushort()).Height; if (!WeaponSystem.SharedHasTileObstacle( character.Position, character.Tile.Height, endPosition, character.PhysicsBody.PhysicsSpace, anyCliffIsAnObstacle: anyCliffIsAnObstacle)) { ServerTimersSystem.AddAction( timeToHit, () => { SharedExplosionHelper.ServerExplode( character: character, protoExplosive: this, protoWeapon: protoWeapon, explosionPreset: this.ExplosionPreset, epicenterPosition: endPosition, damageDescriptionCharacters: this.OverrideDamageDescription, physicsSpace: Server.World.GetPhysicsSpace(), executeExplosionCallback: this.ServerExecuteExplosion); }); } // notify other characters about the explosion using var charactersObserving = Api.Shared.GetTempList <ICharacter>(); var explosionEventRadius = Math.Max(protoWeapon.SoundPresetWeaponDistance.max, this.OverrideDamageDescription.RangeMax) + this.DamageRadius; Server.World.GetCharactersInRadius(endPosition.ToVector2Ushort(), charactersObserving, radius: (byte)Math.Min(byte.MaxValue, explosionEventRadius), onlyPlayers: true); charactersObserving.Remove(character); this.CallClient(charactersObserving.AsList(), _ => _.ClientRemote_OnExplosion(protoWeapon, shotSourcePosition, endPosition)); }
private void ServerExplode(IItem item) { Server.Items.DestroyItem(item); // explode a primitive bomb in player position var character = item.Container.OwnerAsCharacter; if (character is null) { return; } var characterPublicState = character.GetPublicState <PlayerCharacterPublicState>(); if (!characterPublicState.IsDead) { // ensure the wearer is killed by the explosion characterPublicState.CurrentStats.ServerSetHealthCurrent(0); } var targetPosition = character.Position; var protoBomb = ProtoObjectBomb; SharedExplosionHelper.ServerExplode( character: character, protoExplosive: protoBomb, protoWeapon: null, explosionPreset: protoBomb.ExplosionPreset, epicenterPosition: targetPosition, damageDescriptionCharacters: protoBomb.DamageDescriptionCharacters, physicsSpace: Server.World.GetPhysicsSpace(), executeExplosionCallback: protoBomb.ServerExecuteExplosion); // notify all characters about the explosion using var charactersObserving = Api.Shared.GetTempList <ICharacter>(); const byte explosionEventRadius = 40; Server.World.GetCharactersInRadius(targetPosition.ToVector2Ushort(), charactersObserving, radius: explosionEventRadius, onlyPlayers: true); this.CallClient(charactersObserving.AsList(), _ => _.ClientRemote_OnExplosion(targetPosition)); // activate the raidblock if possible (the code is similar to ProtoObjectEplosive) var explosionRadius = (int)Math.Ceiling(protoBomb.DamageRadius); var bounds = new RectangleInt(x: (int)Math.Round(character.Position.X - explosionRadius), y: (int)Math.Round(character.Position.Y - explosionRadius), width: 2 * explosionRadius, height: 2 * explosionRadius); if (RaidingProtectionSystem.SharedCanRaid(bounds, showClientNotification: false)) { // try activate the raidblock LandClaimSystem.ServerOnRaid(bounds, character, isStructureDestroyed: false); } else { // Raiding is not possible now due to raiding window // Find if there is any land claim and in that case notify nearby players // that the damage to objects there was not applied. if (LandClaimSystem.SharedIsLandClaimedByAnyone(bounds)) { using var tempPlayers = Api.Shared.GetTempList <ICharacter>(); Server.World.GetScopedByPlayers(character, tempPlayers); RaidingProtectionSystem.ServerNotifyShowNotificationRaidingNotAvailableNow( tempPlayers.AsList()); } } }