private void ClientExplodeAt( IProtoItemWeapon protoWeapon, Vector2D shotSourcePosition, Vector2D explosionWorldPosition) { var timeToHit = WeaponSystemClientDisplay.SharedCalculateTimeToHit(protoWeapon.FireTracePreset ?? this.FireTracePreset, shotSourcePosition, explosionWorldPosition); ClientTimersSystem.AddAction(timeToHit, () => ExplosionHelper.ClientExplode(explosionWorldPosition, this.ExplosionPreset, this.ExplosionVolume)); }
private void ServerCreateDroppedArrow(WeaponFinalCache weaponCache, Vector2D endPosition) { var shotSourcePosition = WeaponSystemClientDisplay.SharedCalculateWeaponShotWorldPositon( weaponCache.Character, weaponCache.ProtoWeapon, weaponCache.Character.ProtoCharacter, weaponCache.Character.Position, hasTrace: true); var timeToHit = WeaponSystemClientDisplay.SharedCalculateTimeToHit( weaponCache.ProtoWeapon.FireTracePreset ?? weaponCache.ProtoAmmo.FireTracePreset, shotSourcePosition, endPosition); ServerTimersSystem.AddAction( timeToHit, () => { var droplist = ServerGetDroplistFor(weaponCache.ProtoAmmo); var endTilePosition = endPosition.ToVector2Ushort(); var result = ServerDroplistHelper.TryDropToGround( droplist, endTilePosition, // compensate for the server rate to ensure that // it doesn't affect the number of arrows spawned probabilityMultiplier: 1.0 / DropItemsList.DropListItemsCountMultiplier, context: new DropItemContext(weaponCache.Character), out _); if (!result.IsEverythingCreated) { return; } using var charactersObserving = Api.Shared.GetTempList <ICharacter>(); Server.World.GetCharactersInRadius(endTilePosition, charactersObserving, radius: 15, onlyPlayers: true); this.CallClient(charactersObserving.AsList(), _ => _.ClientRemote_OnArrowHitGround(endTilePosition)); }); }
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, () => { ExplosionHelper.ServerExplode( character: character, protoExplosive: this, protoWeapon: protoWeapon, explosionPreset: this.ExplosionPreset, epicenterPosition: endPosition, damageDescriptionCharacters: this.DamageDescription, 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.FireRangeMax) + 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)); }