예제 #1
0
        static void DetachBlock(IMySlimBlock block, IMyAngleGrinder grinder)
        {
            if (!MyAPIGateway.Session.IsServer)
            {
                return;
            }

            MyCubeBlockDefinition blockDef = (MyCubeBlockDefinition)block.BlockDefinition;
            string blockName = blockDef.DisplayNameText;
            string gridName  = $"(Detached {blockName})";

            IMyCubeGrid detachFrom = block.CubeGrid;

            MyObjectBuilder_CubeBlock blockOb = block.GetObjectBuilder();
            MyObjectBuilder_CubeGrid  gridOb  = CreateNewGridOB(block.CubeGrid, blockOb, gridName);

            block.CubeGrid.RemoveBlock(block, true);

            MyCubeGrid createdGrid = MyAPIGateway.Entities.CreateFromObjectBuilderAndAdd(gridOb) as MyCubeGrid;

            if (createdGrid == null)
            {
                Log.Error($"Failed to create a new grid! obj={gridOb}; new entId={gridOb.EntityId.ToString()}");
                MyVisualScriptLogicProvider.SendChatMessageColored($"Failed to create detached block grid!", Color.Red, Log.ModName, grinder.OwnerIdentityId, MyFontEnum.Debug);
                return;
            }

            Log.Info($"Detached '{blockName}' from '{detachFrom.CustomName}' ({detachFrom.EntityId.ToString()}); new grid id={createdGrid.EntityId.ToString()}");

            // sending "to server" so that it happens serverside too if server is a player (or singleplayer).
            DetachEffectsPacket packet = new DetachEffectsPacket(createdGrid.GetBlocks().First());

            AdvancedWeldingMod.Instance.Networking.SendToServer(packet);
        }
예제 #2
0
 void EquippedGrinderChanged(IMyAngleGrinder grinder)
 {
     if (grinder != null && !InformedAboutFeature && MyAPIGateway.Session?.Player != null)
     {
         InformedAboutFeature = true;
         MyVisualScriptLogicProvider.SendChatMessageColored("Type /detach in chat to see grinder features.", Color.Green, Log.ModName, MyAPIGateway.Session.Player.IdentityId);
     }
 }
예제 #3
0
        void Local_EquippedGrinderChanged(IMyAngleGrinder grinder)
        {
            SetUpdate(this, grinder != null);

            if (grinder == null)
            {
                SetLocalDetach(false);
            }
        }
예제 #4
0
        void Local_EquippedGrinderChanged(IMyAngleGrinder grinder)
        {
            SetUpdate(this, grinder != null);

            if (grinder == null)
            {
                SetLocalTarget(null);
            }
        }
예제 #5
0
        void IUpdatable.Update()
        {
            IMyCharacter    chr     = MyAPIGateway.Session?.ControlledObject as IMyCharacter;
            IMyAngleGrinder grinder = chr?.EquippedTool as IMyAngleGrinder;

            if (EquippedGrinder != grinder)
            {
                EquippedGrinder = grinder;
                GrinderChanged?.Invoke(grinder);
            }
        }
예제 #6
0
        void Server_GrindingBlock(IMySlimBlock block, ref MyDamageInformation info, IMyAngleGrinder grinder, ulong attackerSteamId)
        {
            PrecisionData data;

            if (!Server_PrecisionData.TryGetValue(attackerSteamId, out data) || data.GridEntId == 0)
            {
                return;
            }

            if (data.GridEntId != block.CubeGrid.EntityId || data.BlockPos != block.Min)
            {
                info.Amount = 0; // prevent grinding untargetted block
            }
        }
예제 #7
0
        void BeforeDamage(object target, ref MyDamageInformation info)
        {
            try
            {
                if (info.IsDeformation || info.Amount <= 0 || info.Type != MyDamageType.Grind)
                {
                    return;
                }

                IMySlimBlock      block = target as IMySlimBlock;
                IMyFloatingObject fo    = (block == null ? target as IMyFloatingObject : null);

                if (block == null && fo == null)
                {
                    return;
                }

                MyEntity        attacker     = MyEntities.GetEntityById(info.AttackerId);
                IMyAngleGrinder grinder      = attacker as IMyAngleGrinder;
                IMyCharacter    attackerChar = (grinder == null ? attacker as IMyCharacter : null);
                if (grinder == null && attackerChar == null)
                {
                    return;
                }

                ulong attackerSteamId;
                if (grinder != null)
                {
                    attackerSteamId = MyAPIGateway.Players.TryGetSteamId(grinder.OwnerIdentityId);
                }
                else
                {
                    attackerSteamId = MyAPIGateway.Players.TryGetSteamId(attackerChar.ControllerInfo.ControllingIdentityId);
                }

                if (block != null)
                {
                    GrindingBlock?.Invoke(block, ref info, grinder, attackerSteamId);
                }
                else
                {
                    GrindingFloatingObject?.Invoke(fo, ref info, attackerSteamId);
                }
            }
            catch (Exception e)
            {
                Log.Error(e);
            }
        }
예제 #8
0
        void IUpdatable.Update()
        {
            IMyAngleGrinder grinder = Main.GrinderHandler?.EquippedGrinder;

            if (grinder == null)
            {
                return;
            }

            bool inputReadable = !MyAPIGateway.Gui.IsCursorVisible && !MyAPIGateway.Gui.ChatEntryVisible;

            if (TargetBlock == null && inputReadable && MyAPIGateway.Input.IsGameControlPressed(MyControlsSpace.SECONDARY_TOOL_ACTION))
            {
                MyCasterComponent casterComp = grinder?.Components?.Get <MyCasterComponent>();
                IMySlimBlock      target     = casterComp?.HitBlock as IMySlimBlock;

                if (target != null)
                {
                    SetLocalTarget(target);
                }
            }

            if (TargetBlock != null && (!inputReadable || MyAPIGateway.Input.IsNewGameControlReleased(MyControlsSpace.SECONDARY_TOOL_ACTION)))
            {
                SetLocalTarget(null);
            }

            if (TargetBlock != null)
            {
                bool finishedGrinding = TargetBlock.IsFullyDismounted;

                // TODO: some targetting sprite?
                //Vector3D blockCenterPos = Vector3D.Transform(BlockLocalCenter, TargetBlock.CubeGrid.WorldMatrix);
                //float blockSize = (TargetBlock.Max - TargetBlock.Min + Vector3I.One).AbsMin() * TargetBlock.CubeGrid.GridSize;
                //Vector4 color = (finishedGrinding ? Color.Lime : Color.Blue);
                //MyTransparentGeometry.AddPointBillboard(MyStringId.GetOrCompute("WhiteDot"), color, blockCenterPos, blockSize, 0, blendType: BlendTypeEnum.AdditiveTop);

                if (finishedGrinding)
                {
                    Main.Notifications.Print(Channel.Precision, $"Precision Grind: target was grinded!", MyFontEnum.Green, 16);
                }
                else
                {
                    Main.Notifications.Print(Channel.Precision, $"Precision Grind: locked to {TargetBlock.BlockDefinition.DisplayNameText}", MyFontEnum.Debug, 16);
                }
            }
        }
예제 #9
0
        void IUpdatable.Update()
        {
            if (MyAPIGateway.Utilities.IsDedicated)
            {
                return;
            }

            IMyAngleGrinder grinder = Main.GrinderHandler.EquippedGrinder;

            if (grinder == null)
            {
                return;
            }

            bool shouldDetach = !MyAPIGateway.Gui.IsCursorVisible && !MyAPIGateway.Gui.ChatEntryVisible && MyAPIGateway.Input.IsKeyPress(MyKeys.Control);

            if (shouldDetach != Local_DetachData.DetachMode)
            {
                SetLocalDetach(shouldDetach);
            }
        }
예제 #10
0
        void Server_GrindingBlock(IMySlimBlock block, ref MyDamageInformation info, IMyAngleGrinder grinder, ulong attackerSteamId)
        {
            DetachData data = Server_DetachData.GetValueOrDefault(attackerSteamId);

            if (data == null || !data.DetachMode)
            {
                return;
            }

            float grindAmount = info.Amount; // store grinder speed for later use

            info.Amount = 0;                 // prevent grinding while detach mode is enabled

            MyCubeBlockDefinition blockDef = (MyCubeBlockDefinition)block.BlockDefinition;

            if (!blockDef.IsStandAlone || !blockDef.HasPhysics)
            {
                ProgressPacket.Send(attackerSteamId, DetachState.NoStandalone);
                return;
            }

            if (grindAmount == 0)
            {
                ProgressPacket.Send(attackerSteamId, DetachState.ZeroGrindAmount);
                return;
            }

            long owner = block.OwnerId;

            if (owner == 0 && block.CubeGrid.BigOwners != null && block.CubeGrid.BigOwners.Count > 0)
            {
                owner = block.CubeGrid.BigOwners[0];
            }

            if (owner == 0)
            {
                owner = block.BuiltBy;
            }

            if (owner != 0)
            {
                MyRelationsBetweenPlayerAndBlock relation = MyIDModule.GetRelationPlayerBlock(owner, grinder.OwnerIdentityId, MyOwnershipShareModeEnum.Faction);
                if (relation == MyRelationsBetweenPlayerAndBlock.Enemies)
                {
                    ProgressPacket.Send(attackerSteamId, DetachState.EnemyBlock);
                    return;
                }
            }

            MyCubeGrid grid = (MyCubeGrid)block.CubeGrid;

            if (grid.BlocksCount <= 1)
            {
                if (grid.DisplayName.StartsWith("(Detached"))
                {
                    ProgressPacket.Send(attackerSteamId, DetachState.DetachComplete);
                }
                else
                {
                    ProgressPacket.Send(attackerSteamId, DetachState.SingleBlock);
                }
                return;
            }

            // checking safezones doesn't seem necessary, as you cannot grind to begin with...

            if (data.GrindedBlock != block)
            {
                data.GrindedBlock       = block;
                data.GrindedTimes       = 0;
                data.GrindExpiresAtTick = 0;
            }

            int tick = MyAPIGateway.Session.GameplayFrameCounter;

            if (data.GrindExpiresAtTick == 0 || data.GrindExpiresAtTick > tick)
            {
                data.GrindedTimes++;
            }
            else
            {
                data.GrindedTimes = 0;
            }

            data.GrindExpiresAtTick = tick + 30;

            // make it require as much time as it normally would to grind to critical line
            float divideBy           = (block.FatBlock != null ? block.FatBlock.DisassembleRatio : blockDef.DisassembleRatio);
            float finalDamage        = (grindAmount / divideBy) * blockDef.IntegrityPointsPerSec;
            int   grindTimesToDetach = (int)((block.MaxIntegrity * blockDef.CriticalIntegrityRatio) / finalDamage);

            grindTimesToDetach = Math.Max(grindTimesToDetach, (int)(1000 / GrinderCooldownMs)); // at least one second

            if (data.GrindedTimes >= grindTimesToDetach)
            {
                data.GrindedTimes = 0;
                ProgressPacket.Send(attackerSteamId, DetachState.DetachComplete);
                DetachBlock(block, grinder);
            }
            else
            {
                int progress = (data.GrindedTimes * 100) / grindTimesToDetach;
                ProgressPacket.Send(attackerSteamId, DetachState.Detaching, progress);
            }
        }