public override void Register() { ModePacket = new DetachModePacket(); ProgressPacket = new DetachProgressPacket(); if (Networking.IsPlayer) { Local_DetachData = new DetachData(); Main.GrinderHandler.GrinderChanged += Local_EquippedGrinderChanged; DetachProgressPacket.OnReceive += Player_DetachProgressPacketReceived; } if (MyAPIGateway.Session.IsServer) { Server_DetachData = new Dictionary <ulong, DetachData>(); Main.GrindDamageHandler.GrindingBlock += Server_GrindingBlock; DetachModePacket.OnReceive += Server_DetachModePacketReceived; MyVisualScriptLogicProvider.PlayerDisconnected += Server_PlayerDisconnected; } }
void Server_DetachModePacketReceived(DetachModePacket packet) { if (packet.Mode) { DetachData data; if (!Server_DetachData.TryGetValue(packet.OriginalSenderSteamId, out data)) { data = new DetachData(); Server_DetachData[packet.OriginalSenderSteamId] = data; } data.DetachMode = packet.Mode; data.GrindedBlock = null; data.GrindedTimes = 0; data.GrindExpiresAtTick = 0; } else { Server_DetachData.Remove(packet.OriginalSenderSteamId); } }
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); } }