Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Data/BlockVariantGroups.sbc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
<Block Type="MyObjectBuilder_TerminalBlock" Subtype="ChargingStation" />
<Block Type="MyObjectBuilder_TerminalBlock" Subtype="PowerSockets" />
<Block Type="MyObjectBuilder_TerminalBlock" Subtype="TransformerPylon" />
<Block Type="MyObjectBuilder_TerminalBlock" Subtype="LFemaleCStation" />
<Block Type="MyObjectBuilder_TerminalBlock" Subtype="SMaleCStation" />
<Block Type="MyObjectBuilder_TerminalBlock" Subtype="ConveyorHoseAttachment" />
</Blocks>
</BlockVariantGroup>

Expand Down
105 changes: 104 additions & 1 deletion Data/CubeBlocks.sbc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<SubtypeId>ChargingStation</SubtypeId>
</Id>
<DisplayName>Charging Station</DisplayName>
<Description>Left mouse button while no blocks are eqruipped will start placement mode. Right mouse button cancels cable placement mode or disconnects already established connection.</Description>
<Description>Left mouse button while no blocks are equipped will start placement mode. Right mouse button cancels cable placement mode or disconnects already established connection.</Description>
<Icon>Textures\Psycho\Icons\ChargingStation.png</Icon>
<CubeSize>Large</CubeSize>
<BlockTopology>TriangleMesh</BlockTopology>
Expand Down Expand Up @@ -239,5 +239,108 @@
<PCU>5</PCU>
<IsAirTight>false</IsAirTight>
</Definition>



<Definition>
<Id>
<TypeId>TerminalBlock</TypeId>
<SubtypeId>LFemaleCStation</SubtypeId>
</Id>
<DisplayName>F Charging Station</DisplayName>
<Description>Left mouse button while no blocks are eqruipped will start placement mode. Right mouse button cancels cable placement mode or disconnects already established connection.</Description>
<Icon>Textures\Psycho\Icons\PowerSockets.png</Icon>
<CubeSize>Large</CubeSize>
<BlockTopology>TriangleMesh</BlockTopology>
<Size x="1" y="1" z="1" />
<ModelOffset x="0" y="0" z="0" />
<!-- ControlPanel -->
<!-- InteriorPillar -->
<Model>Models\PSYCHO\Large\FemaleChargerFuel\LFemaleCStation.mwm</Model>
<Components>
<Component Subtype="SteelPlate" Count="1" />
<Component Subtype="Construction" Count="1" />
<Component Subtype="Computer" Count="1" />
<Component Subtype="Display" Count="1" />
</Components>
<CriticalComponent Subtype="Construction" Index="0" />
<MountPoints>
<MountPoint Side="Left" StartX="0" StartY="0" EndX="1" EndY="1" />
<MountPoint Side="Front" StartX="0" StartY="0" EndX="1" EndY="1" />
<MountPoint Side="Top" StartX="0" StartY="0" EndX="1" EndY="1" />
</MountPoints>
<IsStandAlone>true</IsStandAlone>
<HasPhysics>true</HasPhysics>
<BuildProgressModels>
<Model BuildPercentUpperBound="0.33" File="Models\Psycho\Large\FemaleChargerFuel\LFemaleCStation_BS1.mwm" />
<Model BuildPercentUpperBound="0.66" File="Models\Psycho\Large\FemaleChargerFuel\LFemaleCStation_BS2.mwm" />
<Model BuildPercentUpperBound="1.00" File="Models\Psycho\Large\FemaleChargerFuel\LFemaleCStation_BS3.mwm" />
</BuildProgressModels>
<BlockPairName>FemaleCStation</BlockPairName>
<MirroringZ>Y</MirroringZ>
<MirroringY>Z</MirroringY>
<EdgeType>Light</EdgeType>
<BuildTimeSeconds>6</BuildTimeSeconds>
<DestroyEffectOffset>
<X>0</X>
<Y>0</Y>
<Z>1.1</Z>
</DestroyEffectOffset>
<PCU>5</PCU>
<IsAirTight>false</IsAirTight>
</Definition>



<Definition>
<Id>
<TypeId>TerminalBlock</TypeId>
<SubtypeId>SMaleCStation</SubtypeId>
</Id>
<DisplayName>M Charging Station</DisplayName>
<Description>Left mouse button while no blocks are eqruipped will start placement mode. Right mouse button cancels cable placement mode or disconnects already established connection.</Description>
<Icon>Textures\Psycho\Icons\PowerSockets.png</Icon>
<CubeSize>Small</CubeSize>
<BlockTopology>TriangleMesh</BlockTopology>
<Size x="1" y="1" z="1" />
<ModelOffset x="0" y="0" z="0" />
<!-- ControlPanel -->
<!-- InteriorPillar -->
<Model>Models\PSYCHO\Small\SMaleCStation\SMaleCStation.mwm</Model>
<Components>
<Component Subtype="SteelPlate" Count="1" />
<Component Subtype="Construction" Count="1" />
<Component Subtype="Computer" Count="1" />
<Component Subtype="Display" Count="1" />
</Components>
<CriticalComponent Subtype="Construction" Index="0" />
<MountPoints>
<MountPoint Side="Bottom" StartX="0.1" EndX="0.9" StartY="0.1" EndY="0.9" />
<MountPoint Side="Left" StartX="0" StartY="0.9" EndX="1" EndY="1" />
<MountPoint Side="Right" StartX="0" StartY="0" EndX="1" EndY="1" />
<MountPoint Side="Front" StartX="0" StartY="0" EndX="1" EndY="1" />
<MountPoint Side="Back" StartX="0" StartY="0" EndX="1" EndY="1" />
<MountPoint Side="Top" StartX="0" StartY="0" EndX="1" EndY="1" />
</MountPoints>
<IsStandAlone>true</IsStandAlone>
<HasPhysics>true</HasPhysics>
<BuildProgressModels>
<Model BuildPercentUpperBound="0.33" File="Models\Psycho\Small\SMaleCStation\SMaleCStation_BS1.mwm" />
<Model BuildPercentUpperBound="0.66" File="Models\Psycho\Small\SMaleCStation\SMaleCStation_BS2.mwm" />
<Model BuildPercentUpperBound="1.00" File="Models\Psycho\Small\SMaleCStation\SMaleCStation_BS3.mwm" />
</BuildProgressModels>
<BlockPairName>MaleCStation</BlockPairName>
<MirroringZ>Y</MirroringZ>
<MirroringY>Z</MirroringY>
<EdgeType>Light</EdgeType>
<BuildTimeSeconds>6</BuildTimeSeconds>
<DestroyEffectOffset>
<X>0</X>
<Y>0</Y>
<Z>1.1</Z>
</DestroyEffectOffset>
<PCU>5</PCU>
<IsAirTight>false</IsAirTight>
</Definition>
</CubeBlocks>
</Definitions>
10 changes: 5 additions & 5 deletions Data/RopeTransparent.sbc
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@
<TypeId>TransparentMaterialDefinition</TypeId>
<SubtypeId>cable</SubtypeId>
</Id>
<AlphaMistingEnable>false</AlphaMistingEnable>
<AlphaSaturation>1</AlphaSaturation>
<AlphaMistingEnable>true</AlphaMistingEnable>
<AlphaSaturation>0.7</AlphaSaturation>
<CanBeAffectedByOtherLights>false</CanBeAffectedByOtherLights>
<IgnoreDepth>false</IgnoreDepth>
<SoftParticleDistanceScale>0.1</SoftParticleDistanceScale>
<Texture>Textures\rope.dds</Texture>
<Texture>Textures\cable.dds</Texture>
</TransparentMaterial>
<TransparentMaterial>
<Id>
<TypeId>TransparentMaterialDefinition</TypeId>
<SubtypeId>cableRed</SubtypeId>
</Id>
<AlphaMistingEnable>false</AlphaMistingEnable>
<AlphaSaturation>1</AlphaSaturation>
<AlphaSaturation>0.5</AlphaSaturation>
<CanBeAffectedByOtherLights>false</CanBeAffectedByOtherLights>
<IgnoreDepth>false</IgnoreDepth>
<SoftParticleDistanceScale>0.1</SoftParticleDistanceScale>
Expand All @@ -31,7 +31,7 @@
<SubtypeId>cableGreen</SubtypeId>
</Id>
<AlphaMistingEnable>false</AlphaMistingEnable>
<AlphaSaturation>1</AlphaSaturation>
<AlphaSaturation>0.5</AlphaSaturation>
<CanBeAffectedByOtherLights>false</CanBeAffectedByOtherLights>
<IgnoreDepth>false</IgnoreDepth>
<SoftParticleDistanceScale>0.1</SoftParticleDistanceScale>
Expand Down
213 changes: 213 additions & 0 deletions Data/Scripts/Faolon/PlayerController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
using Sandbox.Definitions;
using Sandbox.ModAPI;
using SENetworkAPI;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VRage.Game;
using VRage.Game.Components;
using VRage.Game.ModAPI;
using VRage.ModAPI;
using VRage.Network;
using VRage.Utils;
using VRageMath;
using static VRageRender.MyBillboard;

namespace FaolonTether
{
[MySessionComponentDescriptor(MyUpdateOrder.AfterSimulation)]
public class PlayerController : MySessionComponentBase
{
public enum PlayerState { Idle, Interacting }

private PlayerState State = PlayerState.Idle;

private PowerlinePole InteractionObject = null;
private string highlightedName = string.Empty;

// Draw Variables
public const int HIGHLIGHT_PULSE = 300;
VRageMath.Color color;
int thick;
MyStringId cable_vis;

public const ushort NetworkId = 58936;

public override void Init(MyObjectBuilder_SessionComponent sessionComponent)
{
if (!NetworkAPI.IsInitialized)
{
NetworkAPI.Init(NetworkId, "Tether");
}

NetworkAPI.LogNetworkTraffic = true;

// Setup the highlight visuals.
MyEnvironmentDefinition envDef = MyDefinitionManager.Static.EnvironmentDefinition;
color = envDef.ContourHighlightColor;
thick = (int)envDef.ContourHighlightThickness;

// Setup the cable visuals.
cable_vis = MyStringId.GetOrCompute("cable");
}

public override void UpdateAfterSimulation()
{
// client side only check, with an active player in the scene
if (MyAPIGateway.Utilities.IsDedicated ||
MyAPIGateway.Session.Player?.Character == null) return;


if (highlightedName != string.Empty)
{
Sandbox.Game.MyVisualScriptLogicProvider.SetHighlightLocal(highlightedName, -1, HIGHLIGHT_PULSE, color, playerId: MyAPIGateway.Session.Player.IdentityId);
highlightedName = string.Empty;
}

DrawCable();

if (Tools.IsPlayerInMenus()) return;

if (MyAPIGateway.Session?.Player?.Character == null)
return;

IMyEntity tool = MyAPIGateway.Session.Player.Character.EquippedTool;

if (tool != null)
{
MyLog.Default.Info("[Tether] Player is holding a tool, skipping interaction.");
return;
}

bool leftClick = MyAPIGateway.Input.IsNewLeftMouseReleased();
bool rightClick = MyAPIGateway.Input.IsNewRightMouseReleased();

if (rightClick && State == PlayerState.Interacting)
{
MyLog.Default.Info($"[Tether] Right Click - State: {State}");
Cancel();
}

MatrixD playerMatrix = MyAPIGateway.Session.Player.Character.GetHeadMatrix(true);
Tools.RaycastData hit = Tools.RayCastGetHitBlock(playerMatrix);

// stop if there is nothing to interact with
if (hit.Block == null || hit.Block.FatBlock == null) return;

// stop if the object is not a power pole
PowerlinePole pole = hit.Block.FatBlock.GameLogic.GetAs<PowerlinePole>();
if (pole == null) return;

// stop if the object is to far away to interact with
double distance = Vector3D.DistanceSquared(playerMatrix.Translation, hit.Position);
float interactionDistance = Settings.Instance.InteractionDistance * Settings.Instance.InteractionDistance;
if (distance > interactionDistance) return;

if (highlightedName == string.Empty)
{
highlightedName = pole.ModBlock.Name;
Sandbox.Game.MyVisualScriptLogicProvider.SetHighlightLocal(highlightedName, thick, HIGHLIGHT_PULSE, color, playerId: MyAPIGateway.Session.Player.IdentityId);
}

if (leftClick)
{
MyLog.Default.Info($"[Tether] Left Click - State: {State}");
switch (State)
{
case PlayerState.Idle:
Select(pole);
break;
case PlayerState.Interacting:
Connect(pole);
break;
}
}
else if (rightClick)
{
MyLog.Default.Info($"[Tether] Right Click - State: {State}");
switch (State)
{
case PlayerState.Idle:
Disconnect(pole);
break;
case PlayerState.Interacting:
Cancel();
break;
}
}
}

private void DrawCable()
{
if (State != PlayerState.Interacting || InteractionObject == null) return;

PowerlinePole target = null;
Vector4 color = VRageMath.Color.DarkGray;
Vector3 endpoint;

MatrixD playerMatrix = MyAPIGateway.Session.Player.Character.GetHeadMatrix(true);
Tools.RaycastData hit = Tools.RayCastGetHitBlock(playerMatrix);

double distance = Vector3D.DistanceSquared(playerMatrix.Translation, hit.Position);
float interactionDistance = Settings.Instance.InteractionDistance * Settings.Instance.InteractionDistance;

if (hit.Block != null &&
hit.Block.FatBlock != null &&
(target = hit.Block.FatBlock.GameLogic.GetAs<PowerlinePole>()) != null &&
distance < interactionDistance)
{
endpoint = target.DummyAttachPoint;
}
else
{
endpoint = playerMatrix.Translation + (playerMatrix.Forward * Settings.Instance.InteractionDistance);
}

float line_thickness = 0.05f;

// Draw the cable line.
MySimpleObjectDraw.DrawLine(InteractionObject.DummyAttachPoint, endpoint, cable_vis, ref color, line_thickness, BlendTypeEnum.Standard);

}

private void Select(PowerlinePole pole)
{
State = PlayerState.Interacting;
InteractionObject = pole;

MyLog.Default.Info($"[Tether] Select - State: {State}, Interacting: {((InteractionObject == null) ? "null" : InteractionObject.Entity.EntityId.ToString())}");
}

private void Connect(PowerlinePole pole)
{
if (InteractionObject == null)
{
MyLog.Default.Info($"[{Settings.ModName}] cable connection could not occure because the interaction object is null");
Cancel();
return;
}

InteractionObject.ConnectionPoles(pole, MyAPIGateway.Session.Player);
Cancel();

MyLog.Default.Info($"[Tether] Connect - State: {State}, Interacting: {((InteractionObject == null) ? "null" : InteractionObject.Entity.EntityId.ToString())}");
}

private void Disconnect(PowerlinePole pole)
{
State = PlayerState.Interacting;
InteractionObject = pole.DisconnectPoles(MyAPIGateway.Session.Player.IdentityId);

MyLog.Default.Info($"[Tether] Disconnect - State: {State}, Interacting: {((InteractionObject == null) ? "null" : InteractionObject.Entity.EntityId.ToString())}");
}

private void Cancel()
{
State = PlayerState.Idle;
InteractionObject = null;
}
}
}
Loading