예제 #1
0
        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));
        }
예제 #2
0
        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));
            });
        }
예제 #3
0
        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);
                });
예제 #4
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));
        }