Unstable 0.17.1.0
This commit is contained in:
@@ -42,7 +42,7 @@ namespace Barotrauma
|
|||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
IsAlive = msg.ReadBoolean();
|
IsAlive = msg.ReadBoolean();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,395 +112,395 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientWriteInput(IWriteMessage msg)
|
||||||
{
|
{
|
||||||
if (extraData != null)
|
msg.Write((byte)ClientNetObject.CHARACTER_INPUT);
|
||||||
|
|
||||||
|
if (memInput.Count > 60)
|
||||||
{
|
{
|
||||||
switch ((NetEntityEvent.Type)extraData[0])
|
memInput.RemoveRange(60, memInput.Count - 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.Write(LastNetworkUpdateID);
|
||||||
|
byte inputCount = Math.Min((byte)memInput.Count, (byte)60);
|
||||||
|
msg.Write(inputCount);
|
||||||
|
for (int i = 0; i < inputCount; i++)
|
||||||
|
{
|
||||||
|
msg.WriteRangedInteger((int)memInput[i].states, 0, (int)InputNetFlags.MaxVal);
|
||||||
|
msg.Write(memInput[i].intAim);
|
||||||
|
if (memInput[i].states.HasFlag(InputNetFlags.Select) ||
|
||||||
|
memInput[i].states.HasFlag(InputNetFlags.Deselect) ||
|
||||||
|
memInput[i].states.HasFlag(InputNetFlags.Use) ||
|
||||||
|
memInput[i].states.HasFlag(InputNetFlags.Health) ||
|
||||||
|
memInput[i].states.HasFlag(InputNetFlags.Grab))
|
||||||
{
|
{
|
||||||
case NetEntityEvent.Type.InventoryState:
|
msg.Write(memInput[i].interact);
|
||||||
msg.WriteRangedInteger(0, 0, 4);
|
|
||||||
Inventory.ClientWrite(msg, extraData);
|
|
||||||
break;
|
|
||||||
case NetEntityEvent.Type.Treatment:
|
|
||||||
msg.WriteRangedInteger(1, 0, 4);
|
|
||||||
msg.Write(AnimController.Anim == AnimController.Animation.CPR);
|
|
||||||
break;
|
|
||||||
case NetEntityEvent.Type.Status:
|
|
||||||
msg.WriteRangedInteger(2, 0, 4);
|
|
||||||
break;
|
|
||||||
case NetEntityEvent.Type.UpdateTalents:
|
|
||||||
msg.WriteRangedInteger(3, 0, 4);
|
|
||||||
msg.Write((ushort)characterTalents.Count);
|
|
||||||
foreach (var unlockedTalent in characterTalents)
|
|
||||||
{
|
|
||||||
msg.Write(unlockedTalent.Prefab.UintIdentifier);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
|
{
|
||||||
|
if (!(extraData is IEventData eventData)) { throw new Exception($"Malformed character event: expected {nameof(Character)}.{nameof(IEventData)}"); }
|
||||||
|
|
||||||
|
msg.WriteRangedInteger((int)eventData.EventType, (int)EventType.MinValue, (int)EventType.MaxValue);
|
||||||
|
switch (eventData)
|
||||||
|
{
|
||||||
|
case InventoryStateEventData inventoryStateEventData:
|
||||||
|
Inventory.ClientEventWrite(msg, inventoryStateEventData);
|
||||||
|
break;
|
||||||
|
case TreatmentEventData _:
|
||||||
|
msg.Write(AnimController.Anim == AnimController.Animation.CPR);
|
||||||
|
break;
|
||||||
|
case StatusEventData _:
|
||||||
|
//do nothing
|
||||||
|
break;
|
||||||
|
case UpdateTalentsEventData _:
|
||||||
|
msg.Write((ushort)characterTalents.Count);
|
||||||
|
foreach (var unlockedTalent in characterTalents)
|
||||||
|
{
|
||||||
|
msg.Write(unlockedTalent.Prefab.UintIdentifier);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception($"Malformed character event: did not expect {eventData.GetType().Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientReadPosition(IReadMessage msg, float sendingTime)
|
||||||
|
{
|
||||||
|
bool facingRight = AnimController.Dir > 0.0f;
|
||||||
|
|
||||||
|
lastRecvPositionUpdateTime = (float)Lidgren.Network.NetTime.Now;
|
||||||
|
|
||||||
|
AnimController.Frozen = false;
|
||||||
|
Enabled = true;
|
||||||
|
|
||||||
|
UInt16 networkUpdateID = 0;
|
||||||
|
if (msg.ReadBoolean())
|
||||||
|
{
|
||||||
|
networkUpdateID = msg.ReadUInt16();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
msg.Write((byte)ClientNetObject.CHARACTER_INPUT);
|
bool aimInput = msg.ReadBoolean();
|
||||||
|
keys[(int)InputType.Aim].Held = aimInput;
|
||||||
|
keys[(int)InputType.Aim].SetState(false, aimInput);
|
||||||
|
|
||||||
if (memInput.Count > 60)
|
bool shootInput = msg.ReadBoolean();
|
||||||
|
keys[(int)InputType.Shoot].Held = shootInput;
|
||||||
|
keys[(int)InputType.Shoot].SetState(false, shootInput);
|
||||||
|
|
||||||
|
bool useInput = msg.ReadBoolean();
|
||||||
|
keys[(int)InputType.Use].Held = useInput;
|
||||||
|
keys[(int)InputType.Use].SetState(false, useInput);
|
||||||
|
|
||||||
|
if (AnimController is HumanoidAnimController)
|
||||||
{
|
{
|
||||||
memInput.RemoveRange(60, memInput.Count - 60);
|
bool crouching = msg.ReadBoolean();
|
||||||
|
keys[(int)InputType.Crouch].Held = crouching;
|
||||||
|
keys[(int)InputType.Crouch].SetState(false, crouching);
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.Write(LastNetworkUpdateID);
|
bool attackInput = msg.ReadBoolean();
|
||||||
byte inputCount = Math.Min((byte)memInput.Count, (byte)60);
|
keys[(int)InputType.Attack].Held = attackInput;
|
||||||
msg.Write(inputCount);
|
keys[(int)InputType.Attack].SetState(false, attackInput);
|
||||||
for (int i = 0; i < inputCount; i++)
|
|
||||||
{
|
double aimAngle = msg.ReadUInt16() / 65535.0 * 2.0 * Math.PI;
|
||||||
msg.WriteRangedInteger((int)memInput[i].states, 0, (int)InputNetFlags.MaxVal);
|
cursorPosition = AimRefPosition + new Vector2((float)Math.Cos(aimAngle), (float)Math.Sin(aimAngle)) * 500.0f;
|
||||||
msg.Write(memInput[i].intAim);
|
TransformCursorPos();
|
||||||
if (memInput[i].states.HasFlag(InputNetFlags.Select) ||
|
|
||||||
memInput[i].states.HasFlag(InputNetFlags.Deselect) ||
|
bool ragdollInput = msg.ReadBoolean();
|
||||||
memInput[i].states.HasFlag(InputNetFlags.Use) ||
|
keys[(int)InputType.Ragdoll].Held = ragdollInput;
|
||||||
memInput[i].states.HasFlag(InputNetFlags.Health) ||
|
keys[(int)InputType.Ragdoll].SetState(false, ragdollInput);
|
||||||
memInput[i].states.HasFlag(InputNetFlags.Grab))
|
|
||||||
{
|
facingRight = msg.ReadBoolean();
|
||||||
msg.Write(memInput[i].interact);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
msg.WritePadBits();
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
bool entitySelected = msg.ReadBoolean();
|
||||||
{
|
Character selectedCharacter = null;
|
||||||
switch (type)
|
Item selectedItem = null;
|
||||||
|
|
||||||
|
AnimController.Animation animation = AnimController.Animation.None;
|
||||||
|
if (entitySelected)
|
||||||
{
|
{
|
||||||
case ServerNetObject.ENTITY_POSITION:
|
ushort characterID = msg.ReadUInt16();
|
||||||
bool facingRight = AnimController.Dir > 0.0f;
|
ushort itemID = msg.ReadUInt16();
|
||||||
|
selectedCharacter = FindEntityByID(characterID) as Character;
|
||||||
lastRecvPositionUpdateTime = (float)Lidgren.Network.NetTime.Now;
|
selectedItem = FindEntityByID(itemID) as Item;
|
||||||
|
if (characterID != NullEntityID)
|
||||||
AnimController.Frozen = false;
|
{
|
||||||
Enabled = true;
|
bool doingCpr = msg.ReadBoolean();
|
||||||
|
if (doingCpr && SelectedCharacter != null)
|
||||||
UInt16 networkUpdateID = 0;
|
|
||||||
if (msg.ReadBoolean())
|
|
||||||
{
|
{
|
||||||
networkUpdateID = msg.ReadUInt16();
|
animation = AnimController.Animation.CPR;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
bool aimInput = msg.ReadBoolean();
|
|
||||||
keys[(int)InputType.Aim].Held = aimInput;
|
|
||||||
keys[(int)InputType.Aim].SetState(false, aimInput);
|
|
||||||
|
|
||||||
bool shootInput = msg.ReadBoolean();
|
|
||||||
keys[(int)InputType.Shoot].Held = shootInput;
|
|
||||||
keys[(int)InputType.Shoot].SetState(false, shootInput);
|
|
||||||
|
|
||||||
bool useInput = msg.ReadBoolean();
|
|
||||||
keys[(int)InputType.Use].Held = useInput;
|
|
||||||
keys[(int)InputType.Use].SetState(false, useInput);
|
|
||||||
|
|
||||||
if (AnimController is HumanoidAnimController)
|
|
||||||
{
|
|
||||||
bool crouching = msg.ReadBoolean();
|
|
||||||
keys[(int)InputType.Crouch].Held = crouching;
|
|
||||||
keys[(int)InputType.Crouch].SetState(false, crouching);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool attackInput = msg.ReadBoolean();
|
|
||||||
keys[(int)InputType.Attack].Held = attackInput;
|
|
||||||
keys[(int)InputType.Attack].SetState(false, attackInput);
|
|
||||||
|
|
||||||
double aimAngle = msg.ReadUInt16() / 65535.0 * 2.0 * Math.PI;
|
|
||||||
cursorPosition = AimRefPosition + new Vector2((float)Math.Cos(aimAngle), (float)Math.Sin(aimAngle)) * 500.0f;
|
|
||||||
TransformCursorPos();
|
|
||||||
|
|
||||||
bool ragdollInput = msg.ReadBoolean();
|
|
||||||
keys[(int)InputType.Ragdoll].Held = ragdollInput;
|
|
||||||
keys[(int)InputType.Ragdoll].SetState(false, ragdollInput);
|
|
||||||
|
|
||||||
facingRight = msg.ReadBoolean();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool entitySelected = msg.ReadBoolean();
|
|
||||||
Character selectedCharacter = null;
|
|
||||||
Item selectedItem = null;
|
|
||||||
|
|
||||||
AnimController.Animation animation = AnimController.Animation.None;
|
|
||||||
if (entitySelected)
|
|
||||||
{
|
|
||||||
ushort characterID = msg.ReadUInt16();
|
|
||||||
ushort itemID = msg.ReadUInt16();
|
|
||||||
selectedCharacter = FindEntityByID(characterID) as Character;
|
|
||||||
selectedItem = FindEntityByID(itemID) as Item;
|
|
||||||
if (characterID != NullEntityID)
|
|
||||||
{
|
|
||||||
bool doingCpr = msg.ReadBoolean();
|
|
||||||
if (doingCpr && SelectedCharacter != null)
|
|
||||||
{
|
|
||||||
animation = AnimController.Animation.CPR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 pos = new Vector2(
|
|
||||||
msg.ReadSingle(),
|
|
||||||
msg.ReadSingle());
|
|
||||||
float MaxVel = NetConfig.MaxPhysicsBodyVelocity;
|
|
||||||
Vector2 linearVelocity = new Vector2(
|
|
||||||
msg.ReadRangedSingle(-MaxVel, MaxVel, 12),
|
|
||||||
msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
|
|
||||||
linearVelocity = NetConfig.Quantize(linearVelocity, -MaxVel, MaxVel, 12);
|
|
||||||
|
|
||||||
bool fixedRotation = msg.ReadBoolean();
|
|
||||||
float? rotation = null;
|
|
||||||
float? angularVelocity = null;
|
|
||||||
if (!fixedRotation)
|
|
||||||
{
|
|
||||||
rotation = msg.ReadSingle();
|
|
||||||
float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;
|
|
||||||
angularVelocity = msg.ReadRangedSingle(-MaxAngularVel, MaxAngularVel, 8);
|
|
||||||
angularVelocity = NetConfig.Quantize(angularVelocity.Value, -MaxAngularVel, MaxAngularVel, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool readStatus = msg.ReadBoolean();
|
|
||||||
if (readStatus)
|
|
||||||
{
|
|
||||||
ReadStatus(msg);
|
|
||||||
AIController?.ClientRead(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg.ReadPadBits();
|
|
||||||
|
|
||||||
int index = 0;
|
|
||||||
if (GameMain.Client.Character == this && CanMove)
|
|
||||||
{
|
|
||||||
var posInfo = new CharacterStateInfo(
|
|
||||||
pos, rotation,
|
|
||||||
networkUpdateID,
|
|
||||||
facingRight ? Direction.Right : Direction.Left,
|
|
||||||
selectedCharacter, selectedItem, animation);
|
|
||||||
|
|
||||||
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
|
|
||||||
index++;
|
|
||||||
memState.Insert(index, posInfo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var posInfo = new CharacterStateInfo(
|
|
||||||
pos, rotation,
|
|
||||||
linearVelocity, angularVelocity,
|
|
||||||
sendingTime, facingRight ? Direction.Right : Direction.Left,
|
|
||||||
selectedCharacter, selectedItem, animation);
|
|
||||||
|
|
||||||
while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp)
|
|
||||||
index++;
|
|
||||||
memState.Insert(index, posInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case ServerNetObject.ENTITY_EVENT:
|
|
||||||
int eventType = msg.ReadRangedInteger(0, 13);
|
|
||||||
switch (eventType)
|
|
||||||
{
|
|
||||||
case 0: //NetEntityEvent.Type.InventoryState
|
|
||||||
if (Inventory == null)
|
|
||||||
{
|
|
||||||
string errorMsg = "Received an inventory update message for an entity with no inventory ([name], removed: " + Removed + ")";
|
|
||||||
DebugConsole.ThrowError(errorMsg.Replace("[name]", Name));
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ClientRead:NoInventory" + ID, GameAnalyticsManager.ErrorSeverity.Error, errorMsg.Replace("[name]", SpeciesName.Value));
|
|
||||||
|
|
||||||
//read anyway to prevent messing up reading the rest of the message
|
|
||||||
_ = msg.ReadUInt16();
|
|
||||||
byte inventoryItemCount = msg.ReadByte();
|
|
||||||
for (int i = 0; i < inventoryItemCount; i++)
|
|
||||||
{
|
|
||||||
msg.ReadUInt16();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Inventory.ClientRead(type, msg, sendingTime);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1: //NetEntityEvent.Type.Control
|
|
||||||
bool myCharacter = msg.ReadBoolean();
|
|
||||||
byte ownerID = msg.ReadByte();
|
|
||||||
ResetNetState();
|
|
||||||
if (myCharacter)
|
|
||||||
{
|
|
||||||
if (controlled != null)
|
|
||||||
{
|
|
||||||
LastNetworkUpdateID = controlled.LastNetworkUpdateID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsDead) { Controlled = this; }
|
|
||||||
IsRemotePlayer = false;
|
|
||||||
GameMain.Client.HasSpawned = true;
|
|
||||||
GameMain.Client.Character = this;
|
|
||||||
GameMain.LightManager.LosEnabled = true;
|
|
||||||
GameMain.LightManager.LosAlpha = 1f;
|
|
||||||
GameMain.Client.WaitForNextRoundRespawn = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (controlled == this)
|
|
||||||
{
|
|
||||||
Controlled = null;
|
|
||||||
IsRemotePlayer = ownerID > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2: //NetEntityEvent.Type.Status
|
|
||||||
ReadStatus(msg);
|
|
||||||
break;
|
|
||||||
case 3: //NetEntityEvent.Type.UpdateSkills
|
|
||||||
int skillCount = msg.ReadByte();
|
|
||||||
for (int i = 0; i < skillCount; i++)
|
|
||||||
{
|
|
||||||
Identifier skillIdentifier = msg.ReadIdentifier();
|
|
||||||
float skillLevel = msg.ReadSingle();
|
|
||||||
info?.SetSkillLevel(skillIdentifier, skillLevel);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 4: // NetEntityEvent.Type.SetAttackTarget
|
|
||||||
case 5: //NetEntityEvent.Type.ExecuteAttack
|
|
||||||
int attackLimbIndex = msg.ReadByte();
|
|
||||||
UInt16 targetEntityID = msg.ReadUInt16();
|
|
||||||
int targetLimbIndex = msg.ReadByte();
|
|
||||||
Vector2 targetSimPos = new Vector2(msg.ReadSingle(), msg.ReadSingle());
|
|
||||||
//255 = entity already removed, no need to do anything
|
|
||||||
if (attackLimbIndex == 255 || Removed) { break; }
|
|
||||||
if (attackLimbIndex >= AnimController.Limbs.Length)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError($"Received invalid {(eventType == 4 ? "SetAttackTarget" : "ExecuteAttack")} message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Limb attackLimb = AnimController.Limbs[attackLimbIndex];
|
|
||||||
Limb targetLimb = null;
|
|
||||||
IDamageable targetEntity = FindEntityByID(targetEntityID) as IDamageable;
|
|
||||||
if (targetEntity == null && eventType == 4)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError($"Received invalid SetAttackTarget message. Target entity not found (ID {targetEntityID})");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (targetEntity is Character targetCharacter)
|
|
||||||
{
|
|
||||||
if (targetLimbIndex >= targetCharacter.AnimController.Limbs.Length)
|
|
||||||
{
|
|
||||||
DebugConsole.ThrowError($"Received invalid {(eventType == 4 ? "SetAttackTarget" : "ExecuteAttack")} message. Target limb index out of bounds (target character: {targetCharacter.Name}, limb index: {targetLimbIndex}, limb count: {targetCharacter.AnimController.Limbs.Length})");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex];
|
|
||||||
}
|
|
||||||
if (attackLimb?.attack != null && Controlled != this)
|
|
||||||
{
|
|
||||||
if (eventType == 4)
|
|
||||||
{
|
|
||||||
SetAttackTarget(attackLimb, targetEntity, targetSimPos);
|
|
||||||
PlaySound(CharacterSound.SoundType.Attack, maxInterval: 3);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
attackLimb.ExecuteAttack(targetEntity, targetLimb, out _);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 6: //NetEntityEvent.Type.AssignCampaignInteraction
|
|
||||||
byte campaignInteractionType = msg.ReadByte();
|
|
||||||
bool requireConsciousness = msg.ReadBoolean();
|
|
||||||
(GameMain.GameSession?.GameMode as CampaignMode)?.AssignNPCMenuInteraction(this, (CampaignMode.InteractionType)campaignInteractionType);
|
|
||||||
RequireConsciousnessForCustomInteract = requireConsciousness;
|
|
||||||
break;
|
|
||||||
case 7: //NetEntityEvent.Type.ObjectiveManagerState
|
|
||||||
// 1 = order, 2 = objective
|
|
||||||
int msgType = msg.ReadRangedInteger(0, 2);
|
|
||||||
if (msgType == 0) { break; }
|
|
||||||
bool validData = msg.ReadBoolean();
|
|
||||||
if (!validData) { break; }
|
|
||||||
if (msgType == 1)
|
|
||||||
{
|
|
||||||
UInt32 orderPrefabUintIdentifier = msg.ReadUInt32();
|
|
||||||
var orderPrefab = OrderPrefab.Prefabs.Find(p => p.UintIdentifier == orderPrefabUintIdentifier);
|
|
||||||
Identifier option = Identifier.Empty;
|
|
||||||
if (orderPrefab.HasOptions)
|
|
||||||
{
|
|
||||||
int optionIndex = msg.ReadRangedInteger(-1, orderPrefab.AllOptions.Length);
|
|
||||||
if (optionIndex > -1)
|
|
||||||
{
|
|
||||||
option = orderPrefab.AllOptions[optionIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GameMain.GameSession?.CrewManager?.SetOrderHighlight(this, orderPrefab.Identifier, option);
|
|
||||||
}
|
|
||||||
else if (msgType == 2)
|
|
||||||
{
|
|
||||||
Identifier identifier = msg.ReadIdentifier();
|
|
||||||
Identifier option = msg.ReadIdentifier();
|
|
||||||
ushort objectiveTargetEntityId = msg.ReadUInt16();
|
|
||||||
var objectiveTargetEntity = FindEntityByID(objectiveTargetEntityId);
|
|
||||||
GameMain.GameSession?.CrewManager?.CreateObjectiveIcon(this, identifier, option, objectiveTargetEntity);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 8: //NetEntityEvent.Type.TeamChange
|
|
||||||
byte newTeamId = msg.ReadByte();
|
|
||||||
ChangeTeam((CharacterTeamType)newTeamId);
|
|
||||||
break;
|
|
||||||
case 9: //NetEntityEvent.Type.AddToCrew
|
|
||||||
GameMain.GameSession.CrewManager.AddCharacter(this);
|
|
||||||
CharacterTeamType teamID = (CharacterTeamType)msg.ReadByte();
|
|
||||||
ushort itemCount = msg.ReadUInt16();
|
|
||||||
for (int i = 0; i < itemCount; i++)
|
|
||||||
{
|
|
||||||
ushort itemID = msg.ReadUInt16();
|
|
||||||
if (!(Entity.FindEntityByID(itemID) is Item item)) { continue; }
|
|
||||||
item.AllowStealing = true;
|
|
||||||
var wifiComponent = item.GetComponent<WifiComponent>();
|
|
||||||
if (wifiComponent != null)
|
|
||||||
{
|
|
||||||
wifiComponent.TeamID = teamID;
|
|
||||||
}
|
|
||||||
var idCard = item.GetComponent<IdCard>();
|
|
||||||
if (idCard != null)
|
|
||||||
{
|
|
||||||
idCard.TeamID = teamID;
|
|
||||||
idCard.SubmarineSpecificID = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 10: //NetEntityEvent.Type.UpdateExperience
|
|
||||||
int experienceAmount = msg.ReadInt32();
|
|
||||||
info?.SetExperience(experienceAmount);
|
|
||||||
break;
|
|
||||||
case 11: //NetEntityEvent.Type.UpdateTalents:
|
|
||||||
ushort talentCount = msg.ReadUInt16();
|
|
||||||
for (int i = 0; i < talentCount; i++)
|
|
||||||
{
|
|
||||||
bool addedThisRound = msg.ReadBoolean();
|
|
||||||
UInt32 talentIdentifier = msg.ReadUInt32();
|
|
||||||
GiveTalent(talentIdentifier, addedThisRound);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 12: //NetEntityEvent.Type.UpdateMoney:
|
|
||||||
int moneyAmount = msg.ReadInt32();
|
|
||||||
SetMoney(moneyAmount);
|
|
||||||
break;
|
|
||||||
case 13: //NetEntityEvent.Type.UpdatePermanentStats:
|
|
||||||
byte savedStatValueCount = msg.ReadByte();
|
|
||||||
StatTypes statType = (StatTypes)msg.ReadByte();
|
|
||||||
info?.ClearSavedStatValues(statType);
|
|
||||||
for (int i = 0; i < savedStatValueCount; i++)
|
|
||||||
{
|
|
||||||
string statIdentifier = msg.ReadString();
|
|
||||||
float statValue = msg.ReadSingle();
|
|
||||||
bool removeOnDeath = msg.ReadBoolean();
|
|
||||||
info?.ChangeSavedStatValue(statType, statValue, statIdentifier, removeOnDeath, setValue: true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
msg.ReadPadBits();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector2 pos = new Vector2(
|
||||||
|
msg.ReadSingle(),
|
||||||
|
msg.ReadSingle());
|
||||||
|
float MaxVel = NetConfig.MaxPhysicsBodyVelocity;
|
||||||
|
Vector2 linearVelocity = new Vector2(
|
||||||
|
msg.ReadRangedSingle(-MaxVel, MaxVel, 12),
|
||||||
|
msg.ReadRangedSingle(-MaxVel, MaxVel, 12));
|
||||||
|
linearVelocity = NetConfig.Quantize(linearVelocity, -MaxVel, MaxVel, 12);
|
||||||
|
|
||||||
|
bool fixedRotation = msg.ReadBoolean();
|
||||||
|
float? rotation = null;
|
||||||
|
float? angularVelocity = null;
|
||||||
|
if (!fixedRotation)
|
||||||
|
{
|
||||||
|
rotation = msg.ReadSingle();
|
||||||
|
float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;
|
||||||
|
angularVelocity = msg.ReadRangedSingle(-MaxAngularVel, MaxAngularVel, 8);
|
||||||
|
angularVelocity = NetConfig.Quantize(angularVelocity.Value, -MaxAngularVel, MaxAngularVel, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool readStatus = msg.ReadBoolean();
|
||||||
|
if (readStatus)
|
||||||
|
{
|
||||||
|
ReadStatus(msg);
|
||||||
|
AIController?.ClientRead(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.ReadPadBits();
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
if (GameMain.Client.Character == this && CanMove)
|
||||||
|
{
|
||||||
|
var posInfo = new CharacterStateInfo(
|
||||||
|
pos, rotation,
|
||||||
|
networkUpdateID,
|
||||||
|
facingRight ? Direction.Right : Direction.Left,
|
||||||
|
selectedCharacter, selectedItem, animation);
|
||||||
|
|
||||||
|
while (index < memState.Count && NetIdUtils.IdMoreRecent(posInfo.ID, memState[index].ID))
|
||||||
|
index++;
|
||||||
|
memState.Insert(index, posInfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var posInfo = new CharacterStateInfo(
|
||||||
|
pos, rotation,
|
||||||
|
linearVelocity, angularVelocity,
|
||||||
|
sendingTime, facingRight ? Direction.Right : Direction.Left,
|
||||||
|
selectedCharacter, selectedItem, animation);
|
||||||
|
|
||||||
|
while (index < memState.Count && posInfo.Timestamp > memState[index].Timestamp)
|
||||||
|
index++;
|
||||||
|
memState.Insert(index, posInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
|
{
|
||||||
|
EventType eventType = (EventType)msg.ReadRangedInteger((int)EventType.MinValue, (int)EventType.MaxValue);
|
||||||
|
switch (eventType)
|
||||||
|
{
|
||||||
|
case EventType.InventoryState:
|
||||||
|
if (Inventory == null)
|
||||||
|
{
|
||||||
|
string errorMsg = "Received an inventory update message for an entity with no inventory ([name], removed: " + Removed + ")";
|
||||||
|
DebugConsole.ThrowError(errorMsg.Replace("[name]", Name));
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce("CharacterNetworking.ClientRead:NoInventory" + ID, GameAnalyticsManager.ErrorSeverity.Error, errorMsg.Replace("[name]", SpeciesName.Value));
|
||||||
|
|
||||||
|
//read anyway to prevent messing up reading the rest of the message
|
||||||
|
_ = msg.ReadUInt16();
|
||||||
|
byte inventoryItemCount = msg.ReadByte();
|
||||||
|
for (int i = 0; i < inventoryItemCount; i++)
|
||||||
|
{
|
||||||
|
msg.ReadUInt16();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Inventory.ClientEventRead(msg, sendingTime);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.Control:
|
||||||
|
bool myCharacter = msg.ReadBoolean();
|
||||||
|
byte ownerID = msg.ReadByte();
|
||||||
|
ResetNetState();
|
||||||
|
if (myCharacter)
|
||||||
|
{
|
||||||
|
if (controlled != null)
|
||||||
|
{
|
||||||
|
LastNetworkUpdateID = controlled.LastNetworkUpdateID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsDead) { Controlled = this; }
|
||||||
|
IsRemotePlayer = false;
|
||||||
|
GameMain.Client.HasSpawned = true;
|
||||||
|
GameMain.Client.Character = this;
|
||||||
|
GameMain.LightManager.LosEnabled = true;
|
||||||
|
GameMain.LightManager.LosAlpha = 1f;
|
||||||
|
GameMain.Client.WaitForNextRoundRespawn = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (controlled == this)
|
||||||
|
{
|
||||||
|
Controlled = null;
|
||||||
|
IsRemotePlayer = ownerID > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.Status:
|
||||||
|
ReadStatus(msg);
|
||||||
|
break;
|
||||||
|
case EventType.UpdateSkills:
|
||||||
|
int skillCount = msg.ReadByte();
|
||||||
|
for (int i = 0; i < skillCount; i++)
|
||||||
|
{
|
||||||
|
Identifier skillIdentifier = msg.ReadIdentifier();
|
||||||
|
float skillLevel = msg.ReadSingle();
|
||||||
|
info?.SetSkillLevel(skillIdentifier, skillLevel);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.SetAttackTarget:
|
||||||
|
case EventType.ExecuteAttack:
|
||||||
|
int attackLimbIndex = msg.ReadByte();
|
||||||
|
UInt16 targetEntityID = msg.ReadUInt16();
|
||||||
|
int targetLimbIndex = msg.ReadByte();
|
||||||
|
float targetX = msg.ReadSingle();
|
||||||
|
float targetY = msg.ReadSingle();
|
||||||
|
Vector2 targetSimPos = new Vector2(targetX, targetY);
|
||||||
|
//255 = entity already removed, no need to do anything
|
||||||
|
if (attackLimbIndex == 255 || Removed) { break; }
|
||||||
|
if (attackLimbIndex >= AnimController.Limbs.Length)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Limb index out of bounds (character: {Name}, limb index: {attackLimbIndex}, limb count: {AnimController.Limbs.Length})");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Limb attackLimb = AnimController.Limbs[attackLimbIndex];
|
||||||
|
Limb targetLimb = null;
|
||||||
|
IDamageable targetEntity = FindEntityByID(targetEntityID) as IDamageable;
|
||||||
|
if (targetEntity == null && eventType == EventType.SetAttackTarget)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Received invalid SetAttackTarget message. Target entity not found (ID {targetEntityID})");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (targetEntity is Character targetCharacter)
|
||||||
|
{
|
||||||
|
if (targetLimbIndex >= targetCharacter.AnimController.Limbs.Length)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"Received invalid {(eventType == EventType.SetAttackTarget ? "SetAttackTarget" : "ExecuteAttack")} message. Target limb index out of bounds (target character: {targetCharacter.Name}, limb index: {targetLimbIndex}, limb count: {targetCharacter.AnimController.Limbs.Length})");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
targetLimb = targetCharacter.AnimController.Limbs[targetLimbIndex];
|
||||||
|
}
|
||||||
|
if (attackLimb?.attack != null && Controlled != this)
|
||||||
|
{
|
||||||
|
if (eventType == EventType.SetAttackTarget)
|
||||||
|
{
|
||||||
|
SetAttackTarget(attackLimb, targetEntity, targetSimPos);
|
||||||
|
PlaySound(CharacterSound.SoundType.Attack, maxInterval: 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
attackLimb.ExecuteAttack(targetEntity, targetLimb, out _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.AssignCampaignInteraction:
|
||||||
|
byte campaignInteractionType = msg.ReadByte();
|
||||||
|
bool requireConsciousness = msg.ReadBoolean();
|
||||||
|
(GameMain.GameSession?.GameMode as CampaignMode)?.AssignNPCMenuInteraction(this, (CampaignMode.InteractionType)campaignInteractionType);
|
||||||
|
RequireConsciousnessForCustomInteract = requireConsciousness;
|
||||||
|
break;
|
||||||
|
case EventType.ObjectiveManagerState:
|
||||||
|
// 1 = order, 2 = objective
|
||||||
|
AIObjectiveManager.ObjectiveType msgType
|
||||||
|
= (AIObjectiveManager.ObjectiveType)msg.ReadRangedInteger(
|
||||||
|
(int)AIObjectiveManager.ObjectiveType.MinValue,
|
||||||
|
(int)AIObjectiveManager.ObjectiveType.MaxValue);
|
||||||
|
if (msgType == 0) { break; }
|
||||||
|
bool validData = msg.ReadBoolean();
|
||||||
|
if (!validData) { break; }
|
||||||
|
if (msgType == AIObjectiveManager.ObjectiveType.Order)
|
||||||
|
{
|
||||||
|
UInt32 orderPrefabUintIdentifier = msg.ReadUInt32();
|
||||||
|
var orderPrefab = OrderPrefab.Prefabs.Find(p => p.UintIdentifier == orderPrefabUintIdentifier);
|
||||||
|
Identifier option = Identifier.Empty;
|
||||||
|
if (orderPrefab.HasOptions)
|
||||||
|
{
|
||||||
|
int optionIndex = msg.ReadRangedInteger(-1, orderPrefab.AllOptions.Length);
|
||||||
|
if (optionIndex > -1)
|
||||||
|
{
|
||||||
|
option = orderPrefab.AllOptions[optionIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GameMain.GameSession?.CrewManager?.SetOrderHighlight(this, orderPrefab.Identifier, option);
|
||||||
|
}
|
||||||
|
else if (msgType == AIObjectiveManager.ObjectiveType.Objective)
|
||||||
|
{
|
||||||
|
Identifier identifier = msg.ReadIdentifier();
|
||||||
|
Identifier option = msg.ReadIdentifier();
|
||||||
|
ushort objectiveTargetEntityId = msg.ReadUInt16();
|
||||||
|
var objectiveTargetEntity = FindEntityByID(objectiveTargetEntityId);
|
||||||
|
GameMain.GameSession?.CrewManager?.CreateObjectiveIcon(this, identifier, option, objectiveTargetEntity);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.TeamChange:
|
||||||
|
byte newTeamId = msg.ReadByte();
|
||||||
|
ChangeTeam((CharacterTeamType)newTeamId);
|
||||||
|
break;
|
||||||
|
case EventType.AddToCrew:
|
||||||
|
GameMain.GameSession.CrewManager.AddCharacter(this);
|
||||||
|
CharacterTeamType teamID = (CharacterTeamType)msg.ReadByte();
|
||||||
|
ushort itemCount = msg.ReadUInt16();
|
||||||
|
for (int i = 0; i < itemCount; i++)
|
||||||
|
{
|
||||||
|
ushort itemID = msg.ReadUInt16();
|
||||||
|
if (!(Entity.FindEntityByID(itemID) is Item item)) { continue; }
|
||||||
|
item.AllowStealing = true;
|
||||||
|
var wifiComponent = item.GetComponent<WifiComponent>();
|
||||||
|
if (wifiComponent != null)
|
||||||
|
{
|
||||||
|
wifiComponent.TeamID = teamID;
|
||||||
|
}
|
||||||
|
var idCard = item.GetComponent<IdCard>();
|
||||||
|
if (idCard != null)
|
||||||
|
{
|
||||||
|
idCard.TeamID = teamID;
|
||||||
|
idCard.SubmarineSpecificID = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.UpdateExperience:
|
||||||
|
int experienceAmount = msg.ReadInt32();
|
||||||
|
info?.SetExperience(experienceAmount);
|
||||||
|
break;
|
||||||
|
case EventType.UpdateTalents:
|
||||||
|
ushort talentCount = msg.ReadUInt16();
|
||||||
|
for (int i = 0; i < talentCount; i++)
|
||||||
|
{
|
||||||
|
bool addedThisRound = msg.ReadBoolean();
|
||||||
|
UInt32 talentIdentifier = msg.ReadUInt32();
|
||||||
|
GiveTalent(talentIdentifier, addedThisRound);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EventType.UpdateMoney:
|
||||||
|
int moneyAmount = msg.ReadInt32();
|
||||||
|
SetMoney(moneyAmount);
|
||||||
|
break;
|
||||||
|
case EventType.UpdatePermanentStats:
|
||||||
|
byte savedStatValueCount = msg.ReadByte();
|
||||||
|
StatTypes statType = (StatTypes)msg.ReadByte();
|
||||||
|
info?.ClearSavedStatValues(statType);
|
||||||
|
for (int i = 0; i < savedStatValueCount; i++)
|
||||||
|
{
|
||||||
|
string statIdentifier = msg.ReadString();
|
||||||
|
float statValue = msg.ReadSingle();
|
||||||
|
bool removeOnDeath = msg.ReadBoolean();
|
||||||
|
info?.ChangeSavedStatValue(statType, statValue, statIdentifier, removeOnDeath, setValue: true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
msg.ReadPadBits();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Character ReadSpawnData(IReadMessage inc)
|
public static Character ReadSpawnData(IReadMessage inc)
|
||||||
@@ -542,6 +542,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
bool hasOwner = inc.ReadBoolean();
|
bool hasOwner = inc.ReadBoolean();
|
||||||
int ownerId = hasOwner ? inc.ReadByte() : -1;
|
int ownerId = hasOwner ? inc.ReadByte() : -1;
|
||||||
|
int balance = hasOwner ? inc.ReadInt32() : -1;
|
||||||
|
int rewardDistribution = hasOwner ? inc.ReadRangedInteger(0, 100) : -1;
|
||||||
byte teamID = inc.ReadByte();
|
byte teamID = inc.ReadByte();
|
||||||
bool hasAi = inc.ReadBoolean();
|
bool hasAi = inc.ReadBoolean();
|
||||||
Identifier infoSpeciesName = inc.ReadIdentifier();
|
Identifier infoSpeciesName = inc.ReadIdentifier();
|
||||||
@@ -558,6 +560,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
character.TeamID = (CharacterTeamType)teamID;
|
character.TeamID = (CharacterTeamType)teamID;
|
||||||
character.CampaignInteractionType = (CampaignMode.InteractionType)inc.ReadByte();
|
character.CampaignInteractionType = (CampaignMode.InteractionType)inc.ReadByte();
|
||||||
|
character.Wallet.Balance = balance;
|
||||||
|
character.Wallet.RewardDistribution = rewardDistribution;
|
||||||
if (character.CampaignInteractionType != CampaignMode.InteractionType.None)
|
if (character.CampaignInteractionType != CampaignMode.InteractionType.None)
|
||||||
{
|
{
|
||||||
(GameMain.GameSession.GameMode as CampaignMode)?.AssignNPCMenuInteraction(character, character.CampaignInteractionType);
|
(GameMain.GameSession.GameMode as CampaignMode)?.AssignNPCMenuInteraction(character, character.CampaignInteractionType);
|
||||||
@@ -597,7 +601,7 @@ namespace Barotrauma
|
|||||||
: Identifier.Empty)
|
: Identifier.Empty)
|
||||||
.WithManualPriority(orderPriority)
|
.WithManualPriority(orderPriority)
|
||||||
.WithOrderGiver(orderGiver);
|
.WithOrderGiver(orderGiver);
|
||||||
character.SetOrder(order, speak: false, force: true);
|
character.SetOrder(order, isNewOrder: true, speak: false, force: true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
namespace Barotrauma
|
|
||||||
{
|
|
||||||
partial class AfflictionHusk : Affliction
|
|
||||||
{
|
|
||||||
private InfectionState? prevDisplayedMessage;
|
|
||||||
partial void UpdateMessages()
|
|
||||||
{
|
|
||||||
if (character != Character.Controlled) { return; }
|
|
||||||
if (Prefab is AfflictionPrefabHusk { SendMessages: false }) { return; }
|
|
||||||
if (prevDisplayedMessage.HasValue && prevDisplayedMessage.Value == State) { return; }
|
|
||||||
|
|
||||||
switch (State)
|
|
||||||
{
|
|
||||||
case InfectionState.Dormant:
|
|
||||||
if (Strength < DormantThreshold * 0.5f)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GUI.AddMessage(TextManager.Get("HuskDormant"), GUIStyle.Red);
|
|
||||||
break;
|
|
||||||
case InfectionState.Transition:
|
|
||||||
GUI.AddMessage(TextManager.Get("HuskCantSpeak"), GUIStyle.Red);
|
|
||||||
break;
|
|
||||||
case InfectionState.Active:
|
|
||||||
if (character.Params.UseHuskAppendage)
|
|
||||||
{
|
|
||||||
GUI.AddMessage(TextManager.GetWithVariable("HuskActivate", "[Attack]", GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Attack)), GUIStyle.Red);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case InfectionState.Final:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
prevDisplayedMessage = State;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -300,7 +300,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (GameMain.Client != null)
|
if (GameMain.Client != null)
|
||||||
{
|
{
|
||||||
GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Treatment });
|
GameMain.Client.CreateEntityEvent(Character.Controlled, new Character.TreatmentEventData());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -400,7 +400,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GameMain.Client != null)
|
if (GameMain.Client != null)
|
||||||
{
|
{
|
||||||
GameMain.Client.CreateEntityEvent(Character.Controlled, new object[] { NetEntityEvent.Type.Status });
|
GameMain.Client.CreateEntityEvent(Character.Controlled, new Character.StatusEventData());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -573,10 +573,10 @@ namespace Barotrauma
|
|||||||
inWater ? Character.Params.BleedParticleWater : Character.Params.BleedParticleAir,
|
inWater ? Character.Params.BleedParticleWater : Character.Params.BleedParticleAir,
|
||||||
limb.WorldPosition, velocity, 0.0f, Character.AnimController.CurrentHull);
|
limb.WorldPosition, velocity, 0.0f, Character.AnimController.CurrentHull);
|
||||||
|
|
||||||
if (blood != null && !inWater)
|
if (blood != null)
|
||||||
{
|
{
|
||||||
blood.Size *= bloodParticleSize;
|
blood.Size *= bloodParticleSize;
|
||||||
if (!string.IsNullOrEmpty(Character.BloodDecalName) && Rand.Range(0.0f, 1.0f) < 0.05f)
|
if (!inWater && !string.IsNullOrEmpty(Character.BloodDecalName) && Rand.Range(0.0f, 1.0f) < 0.05f)
|
||||||
{
|
{
|
||||||
blood.OnCollision += (Vector2 pos, Hull hull) =>
|
blood.OnCollision += (Vector2 pos, Hull hull) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -523,7 +523,7 @@ namespace Barotrauma
|
|||||||
private string GetSpritePath(ContentPath texturePath)
|
private string GetSpritePath(ContentPath texturePath)
|
||||||
{
|
{
|
||||||
if (!character.IsHumanoid) { return texturePath.Value; }
|
if (!character.IsHumanoid) { return texturePath.Value; }
|
||||||
return GetSpritePath(texturePath, character?.Info);
|
return GetSpritePath(texturePath, character.Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void LoadParamsProjSpecific()
|
partial void LoadParamsProjSpecific()
|
||||||
|
|||||||
@@ -559,7 +559,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GameMain.MainMenuScreen.QuickStart(fixedSeed: false, subName, difficulty, levelGenerationParams);
|
GameMain.MainMenuScreen.QuickStart(fixedSeed: false, subName, difficulty, levelGenerationParams);
|
||||||
|
|
||||||
}, getValidArgs: () => new[] { SubmarineInfo.SavedSubmarines.Select(s => s.Name).Distinct().ToArray() }));
|
}, getValidArgs: () => new[] { SubmarineInfo.SavedSubmarines.Select(s => s.Name).Distinct().OrderBy(s => s).ToArray() }));
|
||||||
|
|
||||||
commands.Add(new Command("steamnetdebug", "steamnetdebug: Toggles Steamworks networking debug logging.", (string[] args) =>
|
commands.Add(new Command("steamnetdebug", "steamnetdebug: Toggles Steamworks networking debug logging.", (string[] args) =>
|
||||||
{
|
{
|
||||||
@@ -628,7 +628,7 @@ namespace Barotrauma
|
|||||||
DebugConsoleMapping.Instance.Remove(key);
|
DebugConsoleMapping.Instance.Remove(key);
|
||||||
NewMessage("Keybind unbound.", GUIStyle.Green);
|
NewMessage("Keybind unbound.", GUIStyle.Green);
|
||||||
return;
|
return;
|
||||||
}, isCheat: false, getValidArgs: () => new[] { DebugConsoleMapping.Instance.Bindings.Keys.Select(keys => keys.ToString()).Distinct().ToArray() }));
|
}, isCheat: false, getValidArgs: () => new[] { DebugConsoleMapping.Instance.Bindings.Keys.Select(keys => keys.ToString()).Distinct().OrderBy(k => k).ToArray() }));
|
||||||
|
|
||||||
commands.Add(new Command("savebinds", "savebinds: Writes current keybinds into the config file.", (string[] args) =>
|
commands.Add(new Command("savebinds", "savebinds: Writes current keybinds into the config file.", (string[] args) =>
|
||||||
{
|
{
|
||||||
@@ -710,6 +710,7 @@ namespace Barotrauma
|
|||||||
commands.Add(new Command("traitorlist", "", (string[] args) => { }));
|
commands.Add(new Command("traitorlist", "", (string[] args) => { }));
|
||||||
AssignRelayToServer("traitorlist", true);
|
AssignRelayToServer("traitorlist", true);
|
||||||
AssignRelayToServer("money", true);
|
AssignRelayToServer("money", true);
|
||||||
|
AssignRelayToServer("showmoney", true);
|
||||||
AssignRelayToServer("setskill", true);
|
AssignRelayToServer("setskill", true);
|
||||||
AssignRelayToServer("readycheck", true);
|
AssignRelayToServer("readycheck", true);
|
||||||
|
|
||||||
@@ -1734,7 +1735,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
return new string[][]
|
return new string[][]
|
||||||
{
|
{
|
||||||
propertyList.Distinct().Select(i => i.Value).ToArray(),
|
propertyList.Distinct().Select(i => i.Value).OrderBy(n => n).ToArray(),
|
||||||
Array.Empty<string>()
|
Array.Empty<string>()
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
@@ -1763,17 +1764,26 @@ namespace Barotrauma
|
|||||||
foreach (var missionPrefab in MissionPrefab.Prefabs)
|
foreach (var missionPrefab in MissionPrefab.Prefabs)
|
||||||
{
|
{
|
||||||
Identifier missionId = (missionPrefab.ConfigElement.Attribute("textidentifier") == null ? missionPrefab.Identifier : missionPrefab.ConfigElement.GetAttributeIdentifier("textidentifier", Identifier.Empty));
|
Identifier missionId = (missionPrefab.ConfigElement.Attribute("textidentifier") == null ? missionPrefab.Identifier : missionPrefab.ConfigElement.GetAttributeIdentifier("textidentifier", Identifier.Empty));
|
||||||
Identifier nameIdentifier = $"missionname.{missionId}".ToIdentifier();
|
addIfMissing($"missionname.{missionId}".ToIdentifier(), language);
|
||||||
if (!tags[language].Contains(nameIdentifier))
|
addIfMissing($"missiondescription.{missionId}".ToIdentifier(), language);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Type itemComponentType in typeof(ItemComponent).Assembly.GetTypes().Where(type => type.IsSubclassOf(typeof(ItemComponent))))
|
||||||
|
{
|
||||||
|
foreach (var property in itemComponentType.GetProperties())
|
||||||
{
|
{
|
||||||
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<LanguageIdentifier>(); }
|
if (!property.IsDefined(typeof(InGameEditable), false)) { continue; }
|
||||||
missingTags[nameIdentifier].Add(language);
|
|
||||||
}
|
string propertyTag = $"{property.DeclaringType.Name}.{property.Name}";
|
||||||
Identifier descriptionIdentifier = $"missiondescription.{missionId}".ToIdentifier();
|
|
||||||
if (!tags[language].Contains(descriptionIdentifier))
|
addIfMissingAll(language,
|
||||||
{
|
propertyTag.ToIdentifier(),
|
||||||
if (!missingTags.ContainsKey(descriptionIdentifier)) { missingTags[descriptionIdentifier] = new HashSet<LanguageIdentifier>(); }
|
property.Name.ToIdentifier(),
|
||||||
missingTags[descriptionIdentifier].Add(language);
|
$"sp.{propertyTag}.name".ToIdentifier());
|
||||||
|
|
||||||
|
addIfMissingAll(language,
|
||||||
|
$"sp.{propertyTag}.description".ToIdentifier(),
|
||||||
|
$"{property.Name.ToIdentifier()}.description".ToIdentifier());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1781,18 +1791,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (sub.Type != SubmarineType.Player || !sub.IsVanillaSubmarine()) { continue; }
|
if (sub.Type != SubmarineType.Player || !sub.IsVanillaSubmarine()) { continue; }
|
||||||
|
|
||||||
Identifier nameIdentifier = $"submarine.name.{sub.Name}".ToIdentifier();
|
addIfMissing($"submarine.name.{sub.Name}".ToIdentifier(), language);
|
||||||
if (!tags[language].Contains(nameIdentifier))
|
addIfMissing(("submarine.description." + sub.Name).ToIdentifier(), language);
|
||||||
{
|
|
||||||
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<LanguageIdentifier>(); }
|
|
||||||
missingTags[nameIdentifier].Add(language);
|
|
||||||
}
|
|
||||||
Identifier descriptionIdentifier = ("submarine.description." + sub.Name).ToIdentifier();
|
|
||||||
if (!tags[language].Contains(descriptionIdentifier))
|
|
||||||
{
|
|
||||||
if (!missingTags.ContainsKey(descriptionIdentifier)) { missingTags[descriptionIdentifier] = new HashSet<LanguageIdentifier>(); }
|
|
||||||
missingTags[descriptionIdentifier].Add(language);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (AfflictionPrefab affliction in AfflictionPrefab.List)
|
foreach (AfflictionPrefab affliction in AfflictionPrefab.List)
|
||||||
@@ -1806,42 +1806,21 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
Identifier afflictionId = affliction.TranslationIdentifier;
|
Identifier afflictionId = affliction.TranslationIdentifier;
|
||||||
Identifier nameIdentifier = $"afflictionname.{afflictionId}".ToIdentifier();
|
addIfMissing($"afflictionname.{afflictionId}".ToIdentifier(), language);
|
||||||
if (!tags[language].Contains(nameIdentifier))
|
addIfMissing($"afflictiondescription.{afflictionId}".ToIdentifier(), language);
|
||||||
{
|
|
||||||
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<LanguageIdentifier>(); }
|
|
||||||
missingTags[nameIdentifier].Add(language);
|
|
||||||
}
|
|
||||||
|
|
||||||
Identifier descriptionIdentifier = $"afflictiondescription.{afflictionId}".ToIdentifier();
|
|
||||||
if (!tags[language].Contains(descriptionIdentifier))
|
|
||||||
{
|
|
||||||
if (!missingTags.ContainsKey(descriptionIdentifier)) { missingTags[descriptionIdentifier] = new HashSet<LanguageIdentifier>(); }
|
|
||||||
missingTags[descriptionIdentifier].Add(language);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var talentTree in TalentTree.JobTalentTrees)
|
foreach (var talentTree in TalentTree.JobTalentTrees)
|
||||||
{
|
{
|
||||||
foreach (var talentSubTree in talentTree.TalentSubTrees)
|
foreach (var talentSubTree in talentTree.TalentSubTrees)
|
||||||
{
|
{
|
||||||
Identifier nameIdentifier = $"talenttree.{talentSubTree.Identifier}".ToIdentifier();
|
addIfMissing($"talenttree.{talentSubTree.Identifier}".ToIdentifier(), language);
|
||||||
if (!tags[language].Contains(nameIdentifier))
|
|
||||||
{
|
|
||||||
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<LanguageIdentifier>(); }
|
|
||||||
missingTags[nameIdentifier].Add(language);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var talent in TalentPrefab.TalentPrefabs)
|
foreach (var talent in TalentPrefab.TalentPrefabs)
|
||||||
{
|
{
|
||||||
Identifier nameIdentifier = $"talentname.{talent.Identifier}".ToIdentifier();
|
addIfMissing($"talentname.{talent.Identifier}".ToIdentifier(), language);
|
||||||
if (!tags[language].Contains(nameIdentifier))
|
|
||||||
{
|
|
||||||
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<LanguageIdentifier>(); }
|
|
||||||
missingTags[nameIdentifier].Add(language);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//check missing entity names
|
//check missing entity names
|
||||||
@@ -1849,17 +1828,25 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Identifier nameIdentifier = ("entityname." + me.Identifier).ToIdentifier();
|
Identifier nameIdentifier = ("entityname." + me.Identifier).ToIdentifier();
|
||||||
if (tags[language].Contains(nameIdentifier)) { continue; }
|
if (tags[language].Contains(nameIdentifier)) { continue; }
|
||||||
|
if (me.HideInMenus) { continue; }
|
||||||
|
|
||||||
|
ContentXElement configElement = null;
|
||||||
|
|
||||||
if (me is ItemPrefab itemPrefab)
|
if (me is ItemPrefab itemPrefab)
|
||||||
{
|
{
|
||||||
nameIdentifier = itemPrefab.ConfigElement?.GetAttributeIdentifier("nameidentifier", nameIdentifier) ?? nameIdentifier;
|
configElement = itemPrefab.ConfigElement;
|
||||||
if (nameIdentifier != null)
|
}
|
||||||
{
|
else if (me is StructurePrefab structurePrefab)
|
||||||
if (tags[language].Contains("entityname." + nameIdentifier)) { continue; }
|
{
|
||||||
}
|
configElement = structurePrefab.ConfigElement;
|
||||||
|
}
|
||||||
|
if (configElement != null)
|
||||||
|
{
|
||||||
|
var overrideIdentifier = configElement.GetAttributeIdentifier("nameidentifier", null);
|
||||||
|
if (overrideIdentifier != null && tags[language].Contains("entityname." + overrideIdentifier)) { continue; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!missingTags.ContainsKey(nameIdentifier)) { missingTags[nameIdentifier] = new HashSet<LanguageIdentifier>(); }
|
addIfMissing(nameIdentifier, language);
|
||||||
missingTags[nameIdentifier].Add(language);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1868,11 +1855,7 @@ namespace Barotrauma
|
|||||||
foreach (LanguageIdentifier language in TextManager.AvailableLanguages)
|
foreach (LanguageIdentifier language in TextManager.AvailableLanguages)
|
||||||
{
|
{
|
||||||
if (language == TextManager.DefaultLanguage) { continue; }
|
if (language == TextManager.DefaultLanguage) { continue; }
|
||||||
if (!tags[language].Contains(englishTag))
|
addIfMissing(englishTag, language);
|
||||||
{
|
|
||||||
if (!missingTags.ContainsKey(englishTag)) { missingTags[englishTag] = new HashSet<LanguageIdentifier>(); }
|
|
||||||
missingTags[englishTag].Add(language);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1920,6 +1903,24 @@ namespace Barotrauma
|
|||||||
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false;
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = false;
|
||||||
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
||||||
SwapLanguage(TextManager.DefaultLanguage);
|
SwapLanguage(TextManager.DefaultLanguage);
|
||||||
|
|
||||||
|
void addIfMissing(Identifier tag, LanguageIdentifier language)
|
||||||
|
{
|
||||||
|
if (!tags[language].Contains(tag))
|
||||||
|
{
|
||||||
|
if (!missingTags.ContainsKey(tag)) { missingTags[tag] = new HashSet<LanguageIdentifier>(); }
|
||||||
|
missingTags[tag].Add(language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void addIfMissingAll(LanguageIdentifier language, params Identifier[] potentialTags)
|
||||||
|
{
|
||||||
|
if (!potentialTags.Any(t => tags[language].Contains(t)))
|
||||||
|
{
|
||||||
|
var tag = potentialTags.First();
|
||||||
|
if (!missingTags.ContainsKey(tag)) { missingTags[tag] = new HashSet<LanguageIdentifier>(); }
|
||||||
|
missingTags[tag].Add(language);
|
||||||
|
}
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
commands.Add(new Command("comparelocafiles", "comparelocafiles [file1] [file2]", (string[] args) =>
|
commands.Add(new Command("comparelocafiles", "comparelocafiles [file1] [file2]", (string[] args) =>
|
||||||
@@ -1944,7 +1945,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
var content1 = getContent(doc1.Root);
|
var content1 = getContent(doc1.Root);
|
||||||
|
var language1 = doc1.Root.GetAttributeIdentifier("language", string.Empty);
|
||||||
|
|
||||||
var content2 = getContent(doc2.Root);
|
var content2 = getContent(doc2.Root);
|
||||||
|
var language2 = doc2.Root.GetAttributeIdentifier("language", string.Empty);
|
||||||
|
|
||||||
foreach (KeyValuePair<string, string> kvp in content1)
|
foreach (KeyValuePair<string, string> kvp in content1)
|
||||||
{
|
{
|
||||||
@@ -1952,12 +1956,9 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
ThrowError($"File 2 doesn't contain the text tag \"{kvp.Key}\"");
|
ThrowError($"File 2 doesn't contain the text tag \"{kvp.Key}\"");
|
||||||
}
|
}
|
||||||
else
|
else if (language1 == language2 && content2[kvp.Key] != kvp.Value)
|
||||||
{
|
{
|
||||||
if (content2[kvp.Key] != kvp.Value)
|
ThrowError($"Texts for the tag \"{kvp.Key}\" don't match:\n1. {kvp.Value}\n2. {content2[kvp.Key]}");
|
||||||
{
|
|
||||||
ThrowError($"Texts for the tag \"{kvp.Key}\" don't match:\n1. {kvp.Value}\n2. {content2[kvp.Key]}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (KeyValuePair<string, string> kvp in content2)
|
foreach (KeyValuePair<string, string> kvp in content2)
|
||||||
@@ -2319,7 +2320,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true;
|
Barotrauma.IO.Validation.SkipValidationInDebugBuilds = true;
|
||||||
File.WriteAllLines(filePath, lines);
|
File.WriteAllLines(filePath, lines);
|
||||||
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
try
|
||||||
|
{
|
||||||
|
ToolBox.OpenFileWithShell(Path.GetFullPath(filePath));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ThrowError($"Failed to open the file \"{filePath}\".", e);
|
||||||
|
}
|
||||||
|
|
||||||
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
|
System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -671,7 +671,7 @@ namespace Barotrauma
|
|||||||
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
if (Character.Controlled != null && ChatMessage.CanUseRadio(Character.Controlled, out WifiComponent radio))
|
||||||
{
|
{
|
||||||
radio.Channel = channel;
|
radio.Channel = channel;
|
||||||
GameMain.Client?.CreateEntityEvent(radio.Item, new object[] { NetEntityEvent.Type.ChangeProperty, radio.SerializableProperties["channel".ToIdentifier()] });
|
GameMain.Client?.CreateEntityEvent(radio.Item, new Item.ChangePropertyEventData(radio.SerializableProperties["channel".ToIdentifier()]));
|
||||||
|
|
||||||
if (setText)
|
if (setText)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
AutoScaleVertical = true,
|
AutoScaleVertical = true,
|
||||||
TextScale = 1.1f,
|
TextScale = 1.1f,
|
||||||
TextGetter = () => FormatCurrency(campaign.Money)
|
TextGetter = () => FormatCurrency(campaign.Wallet.Balance)
|
||||||
};
|
};
|
||||||
|
|
||||||
var pendingAndCrewGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
|
var pendingAndCrewGroup = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.95f), anchor: Anchor.Center,
|
||||||
@@ -630,7 +630,7 @@ namespace Barotrauma
|
|||||||
total += ((InfoSkill)c.UserData).CharacterInfo.Salary;
|
total += ((InfoSkill)c.UserData).CharacterInfo.Salary;
|
||||||
});
|
});
|
||||||
totalBlock.Text = FormatCurrency(total);
|
totalBlock.Text = FormatCurrency(total);
|
||||||
bool enoughMoney = campaign != null ? total <= campaign.Money : true;
|
bool enoughMoney = campaign == null || campaign.Wallet.CanAfford(total);
|
||||||
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
|
totalBlock.TextColor = enoughMoney ? Color.White : Color.Red;
|
||||||
validateHiresButton.Enabled = enoughMoney && pendingList.Content.RectTransform.Children.Any();
|
validateHiresButton.Enabled = enoughMoney && pendingList.Content.RectTransform.Children.Any();
|
||||||
}
|
}
|
||||||
@@ -652,7 +652,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
int total = nonDuplicateHires.Aggregate(0, (total, info) => total + info.Salary);
|
int total = nonDuplicateHires.Aggregate(0, (total, info) => total + info.Salary);
|
||||||
|
|
||||||
if (total > campaign.Money) { return false; }
|
if (!campaign.Wallet.CanAfford(total)) { return false; }
|
||||||
|
|
||||||
bool atLeastOneHired = false;
|
bool atLeastOneHired = false;
|
||||||
foreach (CharacterInfo ci in nonDuplicateHires)
|
foreach (CharacterInfo ci in nonDuplicateHires)
|
||||||
|
|||||||
@@ -299,14 +299,16 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.ShowFPS || GameMain.DebugDraw)
|
if (GameMain.ShowFPS || GameMain.DebugDraw || GameMain.ShowPerf)
|
||||||
{
|
{
|
||||||
DrawString(spriteBatch, new Vector2(10, 10),
|
float y = 10.0f;
|
||||||
|
DrawString(spriteBatch, new Vector2(10, y),
|
||||||
"FPS: " + Math.Round(GameMain.PerformanceCounter.AverageFramesPerSecond),
|
"FPS: " + Math.Round(GameMain.PerformanceCounter.AverageFramesPerSecond),
|
||||||
Color.White, Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
Color.White, Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||||
if (GameMain.GameSession != null && Timing.TotalTime > GameMain.GameSession.RoundStartTime + 1.0)
|
if (GameMain.GameSession != null && Timing.TotalTime > GameMain.GameSession.RoundStartTime + 1.0)
|
||||||
{
|
{
|
||||||
DrawString(spriteBatch, new Vector2(10, 25),
|
y += GameSettings.CurrentConfig.Graphics.TextScale * 15.0f;
|
||||||
|
DrawString(spriteBatch, new Vector2(10, y),
|
||||||
$"Physics: {GameMain.CurrentUpdateRate}",
|
$"Physics: {GameMain.CurrentUpdateRate}",
|
||||||
(GameMain.CurrentUpdateRate < Timing.FixedUpdateRate) ? Color.Red : Color.White, Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
(GameMain.CurrentUpdateRate < Timing.FixedUpdateRate) ? Color.Red : Color.White, Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||||
}
|
}
|
||||||
@@ -336,8 +338,15 @@ namespace Barotrauma
|
|||||||
DrawString(spriteBatch, new Vector2(300, y),
|
DrawString(spriteBatch, new Vector2(300, y),
|
||||||
key + ": " + elapsedMillisecs.ToString("0.00"),
|
key + ": " + elapsedMillisecs.ToString("0.00"),
|
||||||
Color.Lerp(Color.LightGreen, GUIStyle.Red, elapsedMillisecs / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
Color.Lerp(Color.LightGreen, GUIStyle.Red, elapsedMillisecs / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||||
|
|
||||||
y += 15;
|
y += 15;
|
||||||
|
foreach (string childKey in GameMain.PerformanceCounter.GetSavedPartialIdentifiers(key))
|
||||||
|
{
|
||||||
|
elapsedMillisecs = GameMain.PerformanceCounter.GetPartialAverageElapsedMillisecs(key, childKey);
|
||||||
|
DrawString(spriteBatch, new Vector2(315, y),
|
||||||
|
childKey + ": " + elapsedMillisecs.ToString("0.00"),
|
||||||
|
Color.Lerp(Color.LightGreen, GUIStyle.Red, elapsedMillisecs / 10.0f), Color.Black * 0.5f, 0, GUIStyle.SmallFont);
|
||||||
|
y += 15;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Powered.Grids != null)
|
if (Powered.Grids != null)
|
||||||
@@ -1453,7 +1462,7 @@ namespace Barotrauma
|
|||||||
3 => radii.Start,
|
3 => radii.Start,
|
||||||
_ => throw new InvalidOperationException()
|
_ => throw new InvalidOperationException()
|
||||||
};
|
};
|
||||||
int getDirectionIndex(int vertexIndex)
|
static int getDirectionIndex(int vertexIndex)
|
||||||
=> (vertexIndex % 4) switch
|
=> (vertexIndex % 4) switch
|
||||||
{
|
{
|
||||||
0 => (vertexIndex / 4) + 0,
|
0 => (vertexIndex / 4) + 0,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Microsoft.Xna.Framework;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
public class GUIColorPicker : GUIComponent
|
public class GUIColorPicker : GUIComponent, IDisposable
|
||||||
{
|
{
|
||||||
public delegate bool OnColorSelectedHandler(GUIColorPicker component, Color color);
|
public delegate bool OnColorSelectedHandler(GUIColorPicker component, Color color);
|
||||||
public OnColorSelectedHandler? OnColorSelected;
|
public OnColorSelectedHandler? OnColorSelected;
|
||||||
@@ -34,11 +34,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public GUIColorPicker(RectTransform rectT, string? style = null) : base(style, rectT) { }
|
public GUIColorPicker(RectTransform rectT, string? style = null) : base(style, rectT) { }
|
||||||
|
|
||||||
~GUIColorPicker()
|
|
||||||
{
|
|
||||||
DisposeTextures();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Init()
|
private void Init()
|
||||||
{
|
{
|
||||||
int tWidth = Rect.Width;
|
int tWidth = Rect.Width;
|
||||||
@@ -170,10 +165,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisposeTextures()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
mainTexture?.Dispose();
|
mainTexture?.Dispose();
|
||||||
|
mainTexture = null;
|
||||||
hueTexture?.Dispose();
|
hueTexture?.Dispose();
|
||||||
|
hueTexture = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RefreshHue()
|
public void RefreshHue()
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GUIDropDown(RectTransform rectT, LocalizedString text = null, int elementCount = 4, string style = "", bool selectMultiple = false, bool dropAbove = false) : base(style, rectT)
|
public GUIDropDown(RectTransform rectT, LocalizedString text = null, int elementCount = 4, string style = "", bool selectMultiple = false, bool dropAbove = false, Alignment textAlignment = Alignment.CenterLeft) : base(style, rectT)
|
||||||
{
|
{
|
||||||
text ??= new RawLString("");
|
text ??= new RawLString("");
|
||||||
|
|
||||||
@@ -170,9 +170,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
this.selectMultiple = selectMultiple;
|
this.selectMultiple = selectMultiple;
|
||||||
|
|
||||||
button = new GUIButton(new RectTransform(Vector2.One, rectT), text, Alignment.CenterLeft, style: "GUIDropDown")
|
button = new GUIButton(new RectTransform(Vector2.One, rectT), text, textAlignment, style: "GUIDropDown")
|
||||||
{
|
{
|
||||||
OnClicked = OnClicked
|
OnClicked = OnClicked,
|
||||||
|
TextBlock = { OverflowClip = true }
|
||||||
};
|
};
|
||||||
GUIStyle.Apply(button, "", this);
|
GUIStyle.Apply(button, "", this);
|
||||||
button.TextBlock.SetTextPos();
|
button.TextBlock.SetTextPos();
|
||||||
|
|||||||
@@ -96,11 +96,15 @@ namespace Barotrauma
|
|||||||
switch (child.ScaleBasis)
|
switch (child.ScaleBasis)
|
||||||
{
|
{
|
||||||
case ScaleBasis.BothHeight:
|
case ScaleBasis.BothHeight:
|
||||||
|
child.MinSize = new Point(child.Rect.Height, child.MinSize.Y);
|
||||||
|
break;
|
||||||
case ScaleBasis.Smallest when Rect.Height <= Rect.Width:
|
case ScaleBasis.Smallest when Rect.Height <= Rect.Width:
|
||||||
case ScaleBasis.Largest when Rect.Height > Rect.Width:
|
case ScaleBasis.Largest when Rect.Height > Rect.Width:
|
||||||
child.MinSize = new Point((int)((child.Rect.Height * child.RelativeSize.X) / child.RelativeSize.Y), child.MinSize.Y);
|
child.MinSize = new Point((int)((child.Rect.Height * child.RelativeSize.X) / child.RelativeSize.Y), child.MinSize.Y);
|
||||||
break;
|
break;
|
||||||
case ScaleBasis.BothWidth:
|
case ScaleBasis.BothWidth:
|
||||||
|
child.MinSize = new Point(child.MinSize.X, child.Rect.Width);
|
||||||
|
break;
|
||||||
case ScaleBasis.Smallest when Rect.Width <= Rect.Height:
|
case ScaleBasis.Smallest when Rect.Width <= Rect.Height:
|
||||||
case ScaleBasis.Largest when Rect.Width > Rect.Height:
|
case ScaleBasis.Largest when Rect.Width > Rect.Height:
|
||||||
child.MinSize = new Point(child.MinSize.X, (int)((child.Rect.Width * child.RelativeSize.Y) / child.RelativeSize.X));
|
child.MinSize = new Point(child.MinSize.X, (int)((child.Rect.Width * child.RelativeSize.Y) / child.RelativeSize.X));
|
||||||
|
|||||||
@@ -12,9 +12,12 @@ namespace Barotrauma
|
|||||||
Int, Float
|
Int, Float
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public delegate void OnValueEnteredHandler(GUINumberInput numberInput);
|
||||||
|
public OnValueEnteredHandler OnValueEntered;
|
||||||
|
|
||||||
public delegate void OnValueChangedHandler(GUINumberInput numberInput);
|
public delegate void OnValueChangedHandler(GUINumberInput numberInput);
|
||||||
public OnValueChangedHandler OnValueChanged;
|
public OnValueChangedHandler OnValueChanged;
|
||||||
|
|
||||||
public GUITextBox TextBox { get; private set; }
|
public GUITextBox TextBox { get; private set; }
|
||||||
|
|
||||||
public GUIButton PlusButton { get; private set; }
|
public GUIButton PlusButton { get; private set; }
|
||||||
@@ -209,6 +212,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
ClampFloatValue();
|
ClampFloatValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnValueEntered?.Invoke(this);
|
||||||
};
|
};
|
||||||
TextBox.OnEnterPressed += (textBox, text) =>
|
TextBox.OnEnterPressed += (textBox, text) =>
|
||||||
{
|
{
|
||||||
@@ -220,6 +225,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
ClampFloatValue();
|
ClampFloatValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnValueEntered?.Invoke(this);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ namespace Barotrauma
|
|||||||
MoveButton(new Vector2(
|
MoveButton(new Vector2(
|
||||||
Math.Sign(PlayerInput.MousePosition.X - Bar.Rect.Center.X) * Bar.Rect.Width * barScale,
|
Math.Sign(PlayerInput.MousePosition.X - Bar.Rect.Center.X) * Bar.Rect.Width * barScale,
|
||||||
Math.Sign(PlayerInput.MousePosition.Y - Bar.Rect.Center.Y) * Bar.Rect.Height * barScale));
|
Math.Sign(PlayerInput.MousePosition.Y - Bar.Rect.Center.Y) * Bar.Rect.Height * barScale));
|
||||||
|
OnReleased?.Invoke(this, BarScroll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ namespace Barotrauma
|
|||||||
healList.PriceBlock.Text = UpgradeStore.FormatCurrency(totalCost);
|
healList.PriceBlock.Text = UpgradeStore.FormatCurrency(totalCost);
|
||||||
healList.PriceBlock.TextColor = GUIStyle.Red;
|
healList.PriceBlock.TextColor = GUIStyle.Red;
|
||||||
healList.HealButton.Enabled = false;
|
healList.HealButton.Enabled = false;
|
||||||
if (medicalClinic.GetMoney() > totalCost)
|
if (medicalClinic.GetWallet().CanAfford(totalCost))
|
||||||
{
|
{
|
||||||
healList.PriceBlock.TextColor = GUIStyle.TextColorNormal;
|
healList.PriceBlock.TextColor = GUIStyle.TextColorNormal;
|
||||||
if (medicalClinic.PendingHeals.Any())
|
if (medicalClinic.PendingHeals.Any())
|
||||||
@@ -467,7 +467,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GUITextBlock moneyLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), string.Empty, textAlignment: Alignment.TopRight, font: GUIStyle.SubHeadingFont)
|
GUITextBlock moneyLabel = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), balanceLayout.RectTransform), string.Empty, textAlignment: Alignment.TopRight, font: GUIStyle.SubHeadingFont)
|
||||||
{
|
{
|
||||||
TextGetter = () => UpgradeStore.FormatCurrency(medicalClinic.GetMoney()),
|
TextGetter = () => UpgradeStore.FormatCurrency(medicalClinic.GetWallet().Balance),
|
||||||
AutoScaleVertical = true,
|
AutoScaleVertical = true,
|
||||||
TextScale = 1.1f
|
TextScale = 1.1f
|
||||||
};
|
};
|
||||||
@@ -577,7 +577,7 @@ namespace Barotrauma
|
|||||||
GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), footerLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterRight);
|
GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), footerLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterRight);
|
||||||
GUIButton healButton = new GUIButton(new RectTransform(new Vector2(0.33f, 1f), buttonLayout.RectTransform), TextManager.Get("medicalclinic.heal"))
|
GUIButton healButton = new GUIButton(new RectTransform(new Vector2(0.33f, 1f), buttonLayout.RectTransform), TextManager.Get("medicalclinic.heal"))
|
||||||
{
|
{
|
||||||
Enabled = medicalClinic.PendingHeals.Any() && medicalClinic.GetTotalCost() < medicalClinic.GetMoney(),
|
Enabled = medicalClinic.PendingHeals.Any() && medicalClinic.GetWallet().CanAfford(medicalClinic.GetTotalCost()),
|
||||||
OnClicked = (button, _) =>
|
OnClicked = (button, _) =>
|
||||||
{
|
{
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using Barotrauma.Items.Components;
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -67,8 +68,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private CargoManager CargoManager => campaignUI.Campaign.CargoManager;
|
private CargoManager CargoManager => campaignUI.Campaign.CargoManager;
|
||||||
private Location CurrentLocation => campaignUI.Campaign.Map?.CurrentLocation;
|
private Location CurrentLocation => campaignUI.Campaign.Map?.CurrentLocation;
|
||||||
private int PlayerMoney => campaignUI.Campaign.Money;
|
private Wallet PlayerWallet => campaignUI.Campaign.Wallet;
|
||||||
|
|
||||||
private bool IsBuying => activeTab switch
|
private bool IsBuying => activeTab switch
|
||||||
{
|
{
|
||||||
StoreTab.Buy => true,
|
StoreTab.Buy => true,
|
||||||
@@ -715,24 +715,30 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private LocalizedString GetMerchantBalanceText() => GetCurrencyFormatted(CurrentLocation?.StoreCurrentBalance ?? 0);
|
private LocalizedString GetMerchantBalanceText() => GetCurrencyFormatted(CurrentLocation?.StoreCurrentBalance ?? 0);
|
||||||
|
|
||||||
private LocalizedString GetPlayerBalanceText() => GetCurrencyFormatted(PlayerMoney);
|
private LocalizedString GetPlayerBalanceText() => GetCurrencyFormatted(PlayerWallet.Balance);
|
||||||
|
|
||||||
private GUILayoutGroup CreateDealsGroup(GUIListBox parentList, int elementCount = 4)
|
private GUILayoutGroup CreateDealsGroup(GUIListBox parentList, int elementCount = 4)
|
||||||
{
|
{
|
||||||
var elementHeight = (int)(GUI.yScale * 80);
|
var elementHeight = (int)(GUI.yScale * 80);
|
||||||
var frame = new GUIFrame(new RectTransform(new Point(parentList.Content.Rect.Width, elementCount * elementHeight + 3), parent: parentList.Content.RectTransform), style: null);
|
var frame = new GUIFrame(new RectTransform(new Point(parentList.Content.Rect.Width, elementCount * elementHeight + 3), parent: parentList.Content.RectTransform), style: null)
|
||||||
frame.UserData = "deals";
|
{
|
||||||
|
UserData = "deals"
|
||||||
|
};
|
||||||
var dealsGroup = new GUILayoutGroup(new RectTransform(Vector2.One, frame.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter);
|
var dealsGroup = new GUILayoutGroup(new RectTransform(Vector2.One, frame.RectTransform, anchor: Anchor.Center), childAnchor: Anchor.TopCenter);
|
||||||
var dealsHeader = new GUILayoutGroup(new RectTransform(new Point((int)(0.95f * parentList.Content.Rect.Width), elementHeight), parent: dealsGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
var dealsHeader = new GUILayoutGroup(new RectTransform(new Point((int)(0.95f * parentList.Content.Rect.Width), elementHeight), parent: dealsGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft)
|
||||||
dealsHeader.UserData = "header";
|
{
|
||||||
|
UserData = "header"
|
||||||
|
};
|
||||||
var iconWidth = (0.9f * dealsHeader.Rect.Height) / dealsHeader.Rect.Width;
|
var iconWidth = (0.9f * dealsHeader.Rect.Height) / dealsHeader.Rect.Width;
|
||||||
var dealsIcon = new GUIImage(new RectTransform(new Vector2(iconWidth, 0.9f), dealsHeader.RectTransform), "StoreDealIcon", scaleToFit: true);
|
var dealsIcon = new GUIImage(new RectTransform(new Vector2(iconWidth, 0.9f), dealsHeader.RectTransform), "StoreDealIcon", scaleToFit: true);
|
||||||
var text = TextManager.Get(parentList == storeBuyList ? "campaignstore.dailyspecials" : "campaignstore.requestedgoods");
|
var text = TextManager.Get(parentList == storeBuyList ? "campaignstore.dailyspecials" : "campaignstore.requestedgoods");
|
||||||
var dealsText = new GUITextBlock(new RectTransform(new Vector2(1.0f - iconWidth, 0.9f), dealsHeader.RectTransform), text, font: GUIStyle.LargeFont);
|
var dealsText = new GUITextBlock(new RectTransform(new Vector2(1.0f - iconWidth, 0.9f), dealsHeader.RectTransform), text, font: GUIStyle.LargeFont);
|
||||||
storeSpecialColor = dealsIcon.Color;
|
storeSpecialColor = dealsIcon.Color;
|
||||||
dealsText.TextColor = storeSpecialColor;
|
dealsText.TextColor = storeSpecialColor;
|
||||||
var divider = new GUIImage(new RectTransform(new Point(dealsGroup.Rect.Width, 3), dealsGroup.RectTransform), "HorizontalLine");
|
var divider = new GUIImage(new RectTransform(new Point(dealsGroup.Rect.Width, 3), dealsGroup.RectTransform), "HorizontalLine")
|
||||||
divider.UserData = "divider";
|
{
|
||||||
|
UserData = "divider"
|
||||||
|
};
|
||||||
frame.CanBeFocused = dealsGroup.CanBeFocused = dealsHeader.CanBeFocused = dealsIcon.CanBeFocused = dealsText.CanBeFocused = divider.CanBeFocused = false;
|
frame.CanBeFocused = dealsGroup.CanBeFocused = dealsHeader.CanBeFocused = dealsIcon.CanBeFocused = dealsText.CanBeFocused = divider.CanBeFocused = false;
|
||||||
return dealsGroup;
|
return dealsGroup;
|
||||||
}
|
}
|
||||||
@@ -1801,7 +1807,7 @@ namespace Barotrauma
|
|||||||
private void SetOwnedText(GUIComponent itemComponent, GUITextBlock ownedLabel = null)
|
private void SetOwnedText(GUIComponent itemComponent, GUITextBlock ownedLabel = null)
|
||||||
{
|
{
|
||||||
ownedLabel ??= itemComponent?.FindChild("owned", recursive: true) as GUITextBlock;
|
ownedLabel ??= itemComponent?.FindChild("owned", recursive: true) as GUITextBlock;
|
||||||
if (itemComponent == null && ownedLabel == null) { return; }
|
if (itemComponent == null && ownedLabel == null) { return; }
|
||||||
PurchasedItem purchasedItem = itemComponent?.UserData as PurchasedItem;
|
PurchasedItem purchasedItem = itemComponent?.UserData as PurchasedItem;
|
||||||
ItemQuantity itemQuantity = null;
|
ItemQuantity itemQuantity = null;
|
||||||
LocalizedString ownedLabelText = string.Empty;
|
LocalizedString ownedLabelText = string.Empty;
|
||||||
@@ -1970,7 +1976,7 @@ namespace Barotrauma
|
|||||||
DebugConsole.ShowError($"Error clearing the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
DebugConsole.ShowError($"Error clearing the shopping crate: Uknown store tab type. {e.StackTrace.CleanupStackTrace()}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool BuyItems()
|
private bool BuyItems()
|
||||||
{
|
{
|
||||||
@@ -1990,7 +1996,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
itemsToRemove.ForEach(i => itemsToPurchase.Remove(i));
|
itemsToRemove.ForEach(i => itemsToPurchase.Remove(i));
|
||||||
|
|
||||||
if (itemsToPurchase.None() || totalPrice > PlayerMoney) { return false; }
|
if (itemsToPurchase.None() || !PlayerWallet.CanAfford(totalPrice)) { return false; }
|
||||||
|
|
||||||
CargoManager.PurchaseItems(itemsToPurchase, true);
|
CargoManager.PurchaseItems(itemsToPurchase, true);
|
||||||
GameMain.Client?.SendCampaignState();
|
GameMain.Client?.SendCampaignState();
|
||||||
@@ -2047,7 +2053,7 @@ namespace Barotrauma
|
|||||||
if (IsBuying)
|
if (IsBuying)
|
||||||
{
|
{
|
||||||
shoppingCrateTotal.Text = GetCurrencyFormatted(buyTotal);
|
shoppingCrateTotal.Text = GetCurrencyFormatted(buyTotal);
|
||||||
shoppingCrateTotal.TextColor = buyTotal > PlayerMoney ? Color.Red : Color.White;
|
shoppingCrateTotal.TextColor = !PlayerWallet.CanAfford(buyTotal) ? Color.Red : Color.White;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2093,7 +2099,7 @@ namespace Barotrauma
|
|||||||
ActiveShoppingCrateList.Content.RectTransform.Children.Any() &&
|
ActiveShoppingCrateList.Content.RectTransform.Children.Any() &&
|
||||||
activeTab switch
|
activeTab switch
|
||||||
{
|
{
|
||||||
StoreTab.Buy => buyTotal <= PlayerMoney,
|
StoreTab.Buy => PlayerWallet.CanAfford(buyTotal),
|
||||||
StoreTab.Sell => CurrentLocation != null && sellTotal <= CurrentLocation.StoreCurrentBalance,
|
StoreTab.Sell => CurrentLocation != null && sellTotal <= CurrentLocation.StoreCurrentBalance,
|
||||||
StoreTab.SellSub => CurrentLocation != null && sellFromSubTotal <= CurrentLocation.StoreCurrentBalance,
|
StoreTab.SellSub => CurrentLocation != null && sellFromSubTotal <= CurrentLocation.StoreCurrentBalance,
|
||||||
_ => false
|
_ => false
|
||||||
@@ -2109,9 +2115,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private float ownedItemsUpdateTimer = 0.0f, sellableItemsFromSubUpdateTimer = 0.0f;
|
private float ownedItemsUpdateTimer = 0.0f, sellableItemsFromSubUpdateTimer = 0.0f;
|
||||||
private const float timerUpdateInterval = 1.5f;
|
private const float timerUpdateInterval = 1.5f;
|
||||||
|
private readonly Stopwatch updateStopwatch = new Stopwatch();
|
||||||
|
|
||||||
public void Update(float deltaTime)
|
public void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
|
updateStopwatch.Restart();
|
||||||
|
|
||||||
if (GameMain.GraphicsWidth != resolutionWhenCreated.X || GameMain.GraphicsHeight != resolutionWhenCreated.Y)
|
if (GameMain.GraphicsWidth != resolutionWhenCreated.X || GameMain.GraphicsHeight != resolutionWhenCreated.Y)
|
||||||
{
|
{
|
||||||
CreateUI();
|
CreateUI();
|
||||||
@@ -2124,10 +2133,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
var prevOwnedItems = new Dictionary<ItemPrefab, ItemQuantity>(OwnedItems);
|
var prevOwnedItems = new Dictionary<ItemPrefab, ItemQuantity>(OwnedItems);
|
||||||
UpdateOwnedItems();
|
UpdateOwnedItems();
|
||||||
var refresh = (prevOwnedItems.Count != OwnedItems.Count) ||
|
bool refresh = OwnedItems.Count != prevOwnedItems.Count ||
|
||||||
(prevOwnedItems.Select(kvp => kvp.Value.Total).Sum() != OwnedItems.Select(kvp => kvp.Value.Total).Sum()) ||
|
OwnedItems.Values.Sum(v => v.Total) != prevOwnedItems.Values.Sum(v => v.Total) ||
|
||||||
(OwnedItems.Any(kvp => kvp.Value.Total > 0 && !prevOwnedItems.ContainsKey(kvp.Key)) ||
|
OwnedItems.Any(kvp => !prevOwnedItems.TryGetValue(kvp.Key, out ItemQuantity v) || kvp.Value.Total != v.Total) ||
|
||||||
prevOwnedItems.Any(kvp => !OwnedItems.TryGetValue(kvp.Key, out ItemQuantity itemQuantity) || kvp.Value.Total != itemQuantity.Total));
|
prevOwnedItems.Any(kvp => !OwnedItems.ContainsKey(kvp.Key));
|
||||||
if (refresh)
|
if (refresh)
|
||||||
{
|
{
|
||||||
needsItemsToSellRefresh = true;
|
needsItemsToSellRefresh = true;
|
||||||
@@ -2138,8 +2147,13 @@ namespace Barotrauma
|
|||||||
sellableItemsFromSubUpdateTimer += deltaTime;
|
sellableItemsFromSubUpdateTimer += deltaTime;
|
||||||
if (sellableItemsFromSubUpdateTimer >= timerUpdateInterval)
|
if (sellableItemsFromSubUpdateTimer >= timerUpdateInterval)
|
||||||
{
|
{
|
||||||
needsItemsToSellFromSubRefresh = true;
|
var prevSubItems = new List<PurchasedItem>(itemsToSellFromSub);
|
||||||
needsRefresh = true;
|
RefreshItemsToSellFromSub();
|
||||||
|
needsRefresh = needsRefresh ||
|
||||||
|
itemsToSellFromSub.Count != prevSubItems.Count ||
|
||||||
|
itemsToSellFromSub.Sum(i => i.Quantity) != prevSubItems.Sum(i => i.Quantity) ||
|
||||||
|
itemsToSellFromSub.Any(i => !(prevSubItems.FirstOrDefault(prev => prev.ItemPrefab == i.ItemPrefab) is PurchasedItem prev) || i.Quantity != prev.Quantity) ||
|
||||||
|
prevSubItems.Any(prev => itemsToSellFromSub.None(i => i.ItemPrefab == prev.ItemPrefab));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2148,7 +2162,10 @@ namespace Barotrauma
|
|||||||
if (needsRefresh || HavePermissionsChanged()) { Refresh(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
if (needsRefresh || HavePermissionsChanged()) { Refresh(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
||||||
if (needsBuyingRefresh || HavePermissionsChanged(StoreTab.Buy)) { RefreshBuying(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
if (needsBuyingRefresh || HavePermissionsChanged(StoreTab.Buy)) { RefreshBuying(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
||||||
if (needsSellingRefresh || HavePermissionsChanged(StoreTab.Sell)) { RefreshSelling(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
if (needsSellingRefresh || HavePermissionsChanged(StoreTab.Sell)) { RefreshSelling(updateOwned: ownedItemsUpdateTimer > 0.0f); }
|
||||||
if (needsSellingFromSubRefresh || HavePermissionsChanged(StoreTab.SellSub)) { RefreshSellingFromSub(updateItemsToSellFromSub: sellableItemsFromSubUpdateTimer > 0.0f); }
|
if (needsSellingFromSubRefresh || HavePermissionsChanged(StoreTab.SellSub)) { RefreshSellingFromSub(updateOwned: ownedItemsUpdateTimer > 0.0f, updateItemsToSellFromSub: sellableItemsFromSubUpdateTimer > 0.0f); }
|
||||||
|
|
||||||
|
updateStopwatch.Stop();
|
||||||
|
GameMain.PerformanceCounter.AddPartialElapsedTicks("GameSessionUpdate", "StoreUpdate", updateStopwatch.ElapsedTicks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -581,7 +581,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void ShowTransferPrompt()
|
private void ShowTransferPrompt()
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession.Campaign.Money < deliveryFee && deliveryFee > 0)
|
if (!GameMain.GameSession.Campaign.Wallet.CanAfford(deliveryFee) && deliveryFee > 0)
|
||||||
{
|
{
|
||||||
new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("notenoughmoneyfordeliverytext",
|
new GUIMessageBox(TextManager.Get("deliveryrequestheader"), TextManager.GetWithVariables("notenoughmoneyfordeliverytext",
|
||||||
("[currencyname]", currencyLongText),
|
("[currencyname]", currencyLongText),
|
||||||
@@ -629,7 +629,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void ShowBuyPrompt(bool purchaseOnly)
|
private void ShowBuyPrompt(bool purchaseOnly)
|
||||||
{
|
{
|
||||||
if (GameMain.GameSession.Campaign.Money < selectedSubmarine.Price)
|
if (!GameMain.GameSession.Campaign.Wallet.CanAfford(selectedSubmarine.Price))
|
||||||
{
|
{
|
||||||
new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("notenoughmoneyforpurchasetext",
|
new GUIMessageBox(TextManager.Get("purchasesubmarineheader"), TextManager.GetWithVariables("notenoughmoneyforpurchasetext",
|
||||||
("[currencyname]", currencyLongText),
|
("[currencyname]", currencyLongText),
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ namespace Barotrauma
|
|||||||
private GUIFrame pendingChangesFrame = null;
|
private GUIFrame pendingChangesFrame = null;
|
||||||
|
|
||||||
public static Color OwnCharacterBGColor = Color.Gold * 0.7f;
|
public static Color OwnCharacterBGColor = Color.Gold * 0.7f;
|
||||||
|
private bool isTransferMenuOpen;
|
||||||
|
private bool isSending;
|
||||||
|
private GUIComponent transferMenu;
|
||||||
|
private GUIButton transferMenuButton;
|
||||||
|
private float transferMenuOpenState;
|
||||||
|
private bool transferMenuStateCompleted;
|
||||||
|
|
||||||
private class LinkedGUI
|
private class LinkedGUI
|
||||||
{
|
{
|
||||||
@@ -133,8 +139,43 @@ namespace Barotrauma
|
|||||||
SelectInfoFrameTab(SelectedTab);
|
SelectInfoFrameTab(SelectedTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update(float deltaTime)
|
||||||
{
|
{
|
||||||
|
float menuOpenSpeed = deltaTime * 10f;
|
||||||
|
if (isTransferMenuOpen)
|
||||||
|
{
|
||||||
|
if (transferMenuStateCompleted)
|
||||||
|
{
|
||||||
|
transferMenuOpenState = transferMenuOpenState < 0.25f ? Math.Min(0.25f, transferMenuOpenState + (menuOpenSpeed / 2f)) : 0.25f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (transferMenuOpenState > 0.15f)
|
||||||
|
{
|
||||||
|
transferMenuStateCompleted = false;
|
||||||
|
transferMenuOpenState = Math.Max(0.15f, transferMenuOpenState - menuOpenSpeed);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transferMenuStateCompleted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
transferMenuStateCompleted = false;
|
||||||
|
if (transferMenuOpenState < 1f)
|
||||||
|
{
|
||||||
|
transferMenuOpenState = Math.Min(1f, transferMenuOpenState + menuOpenSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transferMenu != null && transferMenuButton != null)
|
||||||
|
{
|
||||||
|
int pos = (int)(transferMenuOpenState * -transferMenu.Rect.Height);
|
||||||
|
transferMenu.RectTransform.AbsoluteOffset = new Point(0, pos);
|
||||||
|
transferMenuButton.RectTransform.AbsoluteOffset = new Point(0, -pos - transferMenu.Rect.Height);
|
||||||
|
}
|
||||||
GameSession.UpdateTalentNotificationIndicator(talentPointNotification);
|
GameSession.UpdateTalentNotificationIndicator(talentPointNotification);
|
||||||
if (Character.Controlled is { } controlled && talentResetButton != null && talentApplyButton != null)
|
if (Character.Controlled is { } controlled && talentResetButton != null && talentApplyButton != null)
|
||||||
{
|
{
|
||||||
@@ -243,10 +284,7 @@ namespace Barotrauma
|
|||||||
var reputationButton = createTabButton(InfoFrameTab.Reputation, "reputation");
|
var reputationButton = createTabButton(InfoFrameTab.Reputation, "reputation");
|
||||||
|
|
||||||
var balanceFrame = new GUIFrame(new RectTransform(new Point(innerLayoutGroup.Rect.Width, innerLayoutGroup.Rect.Height - infoFrameHolderHeight), parent: innerLayoutGroup.RectTransform), style: "InnerFrame");
|
var balanceFrame = new GUIFrame(new RectTransform(new Point(innerLayoutGroup.Rect.Width, innerLayoutGroup.Rect.Height - infoFrameHolderHeight), parent: innerLayoutGroup.RectTransform), style: "InnerFrame");
|
||||||
new GUITextBlock(new RectTransform(Vector2.One, balanceFrame.RectTransform), "", textAlignment: Alignment.Right)
|
GUITextBlock balanceText = new GUITextBlock(new RectTransform(Vector2.One, balanceFrame.RectTransform), string.Empty, textAlignment: Alignment.Right);
|
||||||
{
|
|
||||||
TextGetter = () => TextManager.GetWithVariable("campaignmoney", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", campaignMode.Money))
|
|
||||||
};
|
|
||||||
GUIFrame bottomDisclaimerFrame = new GUIFrame(new RectTransform(new Vector2(contentFrameSize.X, 0.1f), infoFrame.RectTransform)
|
GUIFrame bottomDisclaimerFrame = new GUIFrame(new RectTransform(new Vector2(contentFrameSize.X, 0.1f), infoFrame.RectTransform)
|
||||||
{
|
{
|
||||||
AbsoluteOffset = new Point(contentFrame.Rect.X, contentFrame.Rect.Bottom + GUI.IntScale(8))
|
AbsoluteOffset = new Point(contentFrame.Rect.X, contentFrame.Rect.Bottom + GUI.IntScale(8))
|
||||||
@@ -258,6 +296,18 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
NetLobbyScreen.CreateChangesPendingFrame(pendingChangesFrame);
|
NetLobbyScreen.CreateChangesPendingFrame(pendingChangesFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SetBalanceText(balanceText, campaignMode.Bank.Balance);
|
||||||
|
campaignMode.OnMoneyChanged.RegisterOverwriteExisting(nameof(CreateInfoFrame).ToIdentifier(), e =>
|
||||||
|
{
|
||||||
|
if (e.Wallet != campaignMode.Bank) { return; }
|
||||||
|
SetBalanceText(balanceText, e.Wallet.Balance);
|
||||||
|
});
|
||||||
|
|
||||||
|
static void SetBalanceText(GUITextBlock text, int balance)
|
||||||
|
{
|
||||||
|
text.Text = TextManager.GetWithVariable("bankbalanceformat", "[money]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", balance));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -329,7 +379,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private void CreateCrewListFrame(GUIFrame crewFrame)
|
private void CreateCrewListFrame(GUIFrame crewFrame)
|
||||||
{
|
{
|
||||||
crew = GameMain.GameSession.CrewManager.GetCharacters();
|
// FIXME remove TestScreen stuff
|
||||||
|
crew = GameMain.GameSession?.CrewManager?.GetCharacters() ?? new []{ TestScreen.dummyCharacter };
|
||||||
teamIDs = crew.Select(c => c.TeamID).Distinct().ToList();
|
teamIDs = crew.Select(c => c.TeamID).Distinct().ToList();
|
||||||
|
|
||||||
// Show own team first when there's more than one team
|
// Show own team first when there's more than one team
|
||||||
@@ -743,7 +794,7 @@ namespace Barotrauma
|
|||||||
Client client = userData as Client;
|
Client client = userData as Client;
|
||||||
|
|
||||||
GUIComponent existingPreview = infoFrameHolder.FindChild("SelectedCharacter");
|
GUIComponent existingPreview = infoFrameHolder.FindChild("SelectedCharacter");
|
||||||
if (existingPreview != null) infoFrameHolder.RemoveChild(existingPreview);
|
if (existingPreview != null) { infoFrameHolder.RemoveChild(existingPreview); }
|
||||||
|
|
||||||
GUIFrame background = new GUIFrame(new RectTransform(new Vector2(0.543f, 0.717f), infoFrameHolder.RectTransform, Anchor.TopLeft, Pivot.TopRight) { RelativeOffset = new Vector2(-0.145f, 0) })
|
GUIFrame background = new GUIFrame(new RectTransform(new Vector2(0.543f, 0.717f), infoFrameHolder.RectTransform, Anchor.TopLeft, Pivot.TopRight) { RelativeOffset = new Vector2(-0.145f, 0) })
|
||||||
{
|
{
|
||||||
@@ -760,17 +811,291 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
GUIComponent preview = character.Info.CreateInfoFrame(background, false, GetPermissionIcon(GameMain.Client.ConnectedClients.Find(c => c.Character == character)));
|
GUIComponent preview = character.Info.CreateInfoFrame(background, false, GetPermissionIcon(GameMain.Client.ConnectedClients.Find(c => c.Character == character)));
|
||||||
GameMain.Client.SelectCrewCharacter(character, preview);
|
GameMain.Client.SelectCrewCharacter(character, preview);
|
||||||
|
CreateWalletFrame(background, character);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (client != null)
|
else if (client != null)
|
||||||
{
|
{
|
||||||
GUIComponent preview = CreateClientInfoFrame(background, client, GetPermissionIcon(client));
|
GUIComponent preview = CreateClientInfoFrame(background, client, GetPermissionIcon(client));
|
||||||
if (GameMain.NetworkMember != null) GameMain.Client.SelectCrewClient(client, preview);
|
if (GameMain.NetworkMember != null) { GameMain.Client.SelectCrewClient(client, preview); }
|
||||||
|
CreateWalletFrame(background, client.Character);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CreateWalletFrame(GUIComponent parent, Character character)
|
||||||
|
{
|
||||||
|
if (character is null) { throw new ArgumentNullException(nameof(character), "Tried to create a wallet frame for a null character");}
|
||||||
|
isTransferMenuOpen = false;
|
||||||
|
transferMenuOpenState = 1f;
|
||||||
|
ImmutableArray<Character> salaryCrew = Mission.GetSalaryEligibleCrew().Where(c => c != character).ToImmutableArray();
|
||||||
|
|
||||||
|
Wallet targetWallet = character.Wallet;
|
||||||
|
|
||||||
|
GUIFrame walletFrame = new GUIFrame(new RectTransform(new Vector2(1f, 0.35f), parent.RectTransform, anchor: Anchor.TopLeft)
|
||||||
|
{
|
||||||
|
RelativeOffset = new Vector2(0, 1.02f)
|
||||||
|
});
|
||||||
|
|
||||||
|
GUILayoutGroup walletLayout = new GUILayoutGroup(new RectTransform(ToolBox.PaddingSizeParentRelative(walletFrame.RectTransform, 0.9f), walletFrame.RectTransform, anchor: Anchor.Center));
|
||||||
|
|
||||||
|
GUILayoutGroup headerLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.33f), walletLayout.RectTransform), isHorizontal: true);
|
||||||
|
GUIImage icon = new GUIImage(new RectTransform(Vector2.One, headerLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight), style: "StoreTradingIcon", scaleToFit: true);
|
||||||
|
float relativeX = icon.RectTransform.NonScaledSize.X / (float)icon.Parent.RectTransform.NonScaledSize.X;
|
||||||
|
GUILayoutGroup headerTextLayout = new GUILayoutGroup(new RectTransform(new Vector2(1.0f - relativeX, 1f), headerLayout.RectTransform), isHorizontal: true) { Stretch = true };
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), headerTextLayout.RectTransform), TextManager.Get("crewwallet.wallet"), font: GUIStyle.LargeFont);
|
||||||
|
GUITextBlock moneyBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), headerTextLayout.RectTransform), UpgradeStore.FormatCurrency(targetWallet.Balance), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right);
|
||||||
|
|
||||||
|
GUILayoutGroup middleLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.66f), walletLayout.RectTransform));
|
||||||
|
GUILayoutGroup salaryTextLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), middleLayout.RectTransform), isHorizontal: true);
|
||||||
|
GUITextBlock salaryTitle = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), salaryTextLayout.RectTransform), TextManager.Get("crewwallet.salary"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.BottomLeft);
|
||||||
|
GUITextBlock rewardBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 1f), salaryTextLayout.RectTransform), $"{Mission.GetRewardShare(targetWallet.RewardDistribution, salaryCrew, Option<int>.None()).Percentage}%", textAlignment: Alignment.BottomRight);
|
||||||
|
GUILayoutGroup sliderLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), middleLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.Center);
|
||||||
|
GUIScrollBar salarySlider = new GUIScrollBar(new RectTransform(new Vector2(0.9f, 1f), sliderLayout.RectTransform), style: "GUISlider", barSize: 0.03f)
|
||||||
|
{
|
||||||
|
Range = Vector2.UnitY,
|
||||||
|
BarScrollValue = targetWallet.RewardDistribution / 100f,
|
||||||
|
Step = 0.01f,
|
||||||
|
BarSize = 0.1f,
|
||||||
|
OnMoved = (bar, scroll) =>
|
||||||
|
{
|
||||||
|
rewardBlock.Text = $"{Mission.GetRewardShare((int)(scroll * 100f), salaryCrew, Option<int>.None()).Percentage}%";
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
OnReleased = (bar, scroll) =>
|
||||||
|
{
|
||||||
|
int newRewardDistribution = (int)(scroll * 100);
|
||||||
|
if (newRewardDistribution == targetWallet.RewardDistribution) { return false; }
|
||||||
|
SetRewardDistribution(character, newRewardDistribution);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// @formatter:off
|
||||||
|
GUIScissorComponent scissorComponent = new GUIScissorComponent(new RectTransform(new Vector2(0.85f, 1.25f), walletFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter))
|
||||||
|
{
|
||||||
|
CanBeFocused = false
|
||||||
|
};
|
||||||
|
transferMenu = new GUIFrame(new RectTransform(Vector2.One, scissorComponent.Content.RectTransform));
|
||||||
|
|
||||||
|
GUILayoutGroup transferMenuLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.8f), transferMenu.RectTransform, Anchor.BottomLeft), childAnchor: Anchor.Center);
|
||||||
|
GUILayoutGroup paddedTransferMenuLayout = new GUILayoutGroup(new RectTransform(ToolBox.PaddingSizeParentRelative(transferMenuLayout.RectTransform, 0.85f), transferMenuLayout.RectTransform));
|
||||||
|
GUILayoutGroup mainLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), paddedTransferMenuLayout.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft);
|
||||||
|
GUILayoutGroup leftLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1f), mainLayout.RectTransform));
|
||||||
|
GUITextBlock leftName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), leftLayout.RectTransform), character.Name, textAlignment: Alignment.CenterLeft, font: GUIStyle.SubHeadingFont);
|
||||||
|
GUITextBlock leftBalance = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), leftLayout.RectTransform), UpgradeStore.FormatCurrency(targetWallet.Balance), textAlignment: Alignment.Left) { TextColor = GUIStyle.Blue };
|
||||||
|
GUILayoutGroup rightLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.5f, 1f), mainLayout.RectTransform), childAnchor: Anchor.TopRight);
|
||||||
|
GUITextBlock rightName = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), rightLayout.RectTransform), string.Empty, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterRight);
|
||||||
|
GUITextBlock rightBalance = new GUITextBlock(new RectTransform(new Vector2(1f, 0.5f), rightLayout.RectTransform), string.Empty, textAlignment: Alignment.Right) { TextColor = GUIStyle.Red };
|
||||||
|
GUILayoutGroup centerLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.9f), mainLayout.RectTransform, Anchor.Center), childAnchor: Anchor.Center) { IgnoreLayoutGroups = true };
|
||||||
|
new GUIFrame(new RectTransform(new Vector2(0f, 1f), centerLayout.RectTransform, Anchor.Center), style: "VerticalLine") { IgnoreLayoutGroups = true };
|
||||||
|
GUIButton centerButton = new GUIButton(new RectTransform(new Vector2(0.6f), centerLayout.RectTransform, scaleBasis: ScaleBasis.BothHeight, anchor: Anchor.Center), style: "GUIButtonTransferArrow");
|
||||||
|
|
||||||
|
GUILayoutGroup inputLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.25f), paddedTransferMenuLayout.RectTransform), childAnchor: Anchor.Center);
|
||||||
|
GUINumberInput transferAmountInput = new GUINumberInput(new RectTransform(new Vector2(0.5f, 1f), inputLayout.RectTransform), GUINumberInput.NumberType.Int, hidePlusMinusButtons: true)
|
||||||
|
{
|
||||||
|
MinValueInt = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
GUILayoutGroup buttonLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.25f), paddedTransferMenuLayout.RectTransform), childAnchor: Anchor.Center);
|
||||||
|
GUILayoutGroup centerButtonLayout = new GUILayoutGroup(new RectTransform(new Vector2(0.75f, 1f), buttonLayout.RectTransform), isHorizontal: true);
|
||||||
|
GUIButton confirmButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1f), centerButtonLayout.RectTransform), TextManager.Get("confirm"), style: "GUIButtonFreeScale") { Enabled = false };
|
||||||
|
GUIButton resetButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1f), centerButtonLayout.RectTransform), TextManager.Get("reset"), style: "GUIButtonFreeScale") { Enabled = false };
|
||||||
|
// @formatter:on
|
||||||
|
transferMenuButton = new GUIButton(new RectTransform(new Vector2(0.5f, 0.2f), walletFrame.RectTransform, Anchor.BottomCenter, Pivot.TopCenter), style: "UIToggleButtonVertical")
|
||||||
|
{
|
||||||
|
OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
isTransferMenuOpen = !isTransferMenuOpen;
|
||||||
|
if (!isTransferMenuOpen)
|
||||||
|
{
|
||||||
|
transferAmountInput.IntValue = 0;
|
||||||
|
}
|
||||||
|
ToggleTransferMenuIcon(button, open: isTransferMenuOpen);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ToggleTransferMenuIcon(transferMenuButton, open: isTransferMenuOpen);
|
||||||
|
ToggleCenterButton(centerButton, isSending);
|
||||||
|
|
||||||
|
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign campaign)
|
||||||
|
{
|
||||||
|
if (!(Character.Controlled is { } myCharacter))
|
||||||
|
{
|
||||||
|
salarySlider.Enabled = false;
|
||||||
|
transferAmountInput.Enabled = false;
|
||||||
|
centerButton.Enabled = false;
|
||||||
|
confirmButton.Enabled = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasPermissions = campaign.AllowedToManageCampaign();
|
||||||
|
salarySlider.Enabled = hasPermissions;
|
||||||
|
Wallet otherWallet;
|
||||||
|
|
||||||
|
switch (hasPermissions)
|
||||||
|
{
|
||||||
|
case true:
|
||||||
|
rightName.Text = TextManager.Get("crewwallet.bank");
|
||||||
|
otherWallet = campaign.Bank;
|
||||||
|
break;
|
||||||
|
case false when character == myCharacter:
|
||||||
|
rightName.Text = TextManager.Get("crewwallet.bank");
|
||||||
|
otherWallet = campaign.Bank;
|
||||||
|
isSending = true;
|
||||||
|
ToggleCenterButton(centerButton, isSending);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rightName.Text = myCharacter.Name;
|
||||||
|
otherWallet = campaign.PersonalWallet;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasPermissions)
|
||||||
|
{
|
||||||
|
centerButton.Enabled = centerButton.CanBeFocused = false;
|
||||||
|
salarySlider.Enabled = salarySlider.CanBeFocused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
leftBalance.Text = UpgradeStore.FormatCurrency(otherWallet.Balance);
|
||||||
|
|
||||||
|
UpdateAllInputs();
|
||||||
|
|
||||||
|
centerButton.OnClicked = (btn, o) =>
|
||||||
|
{
|
||||||
|
isSending = !isSending;
|
||||||
|
ToggleCenterButton(btn, isSending);
|
||||||
|
UpdateAllInputs();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
transferAmountInput.OnValueChanged = input =>
|
||||||
|
{
|
||||||
|
UpdateInputs();
|
||||||
|
};
|
||||||
|
|
||||||
|
transferAmountInput.OnValueEntered = input =>
|
||||||
|
{
|
||||||
|
UpdateAllInputs();
|
||||||
|
};
|
||||||
|
|
||||||
|
campaign.OnMoneyChanged.RegisterOverwriteExisting(nameof(CreateWalletFrame).ToIdentifier(), e =>
|
||||||
|
{
|
||||||
|
if (e.Wallet == targetWallet)
|
||||||
|
{
|
||||||
|
moneyBlock.Text = UpgradeStore.FormatCurrency(e.Info.Balance);
|
||||||
|
salarySlider.BarScrollValue = e.Info.RewardDistribution / 100f;
|
||||||
|
}
|
||||||
|
UpdateAllInputs();
|
||||||
|
});
|
||||||
|
|
||||||
|
resetButton.OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
transferAmountInput.IntValue = 0;
|
||||||
|
UpdateAllInputs();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
confirmButton.OnClicked = (button, o) =>
|
||||||
|
{
|
||||||
|
int amount = transferAmountInput.IntValue;
|
||||||
|
if (amount == 0) { return false; }
|
||||||
|
|
||||||
|
Option<Character> target1 = Option<Character>.Some(character),
|
||||||
|
target2 = otherWallet == campaign.Bank ? Option<Character>.None() : Option<Character>.Some(myCharacter);
|
||||||
|
if (isSending) { (target1, target2) = (target2, target1); }
|
||||||
|
|
||||||
|
SendTransaction(target1, target2, amount);
|
||||||
|
isTransferMenuOpen = false;
|
||||||
|
ToggleTransferMenuIcon(transferMenuButton, isTransferMenuOpen);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
void UpdateAllInputs()
|
||||||
|
{
|
||||||
|
UpdateInputs();
|
||||||
|
UpdateMaxInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateInputs()
|
||||||
|
{
|
||||||
|
confirmButton.Enabled = resetButton.Enabled = transferAmountInput.IntValue > 0;
|
||||||
|
if (transferAmountInput.IntValue == 0)
|
||||||
|
{
|
||||||
|
rightBalance.Text = UpgradeStore.FormatCurrency(otherWallet.Balance);
|
||||||
|
rightBalance.TextColor = GUIStyle.TextColorNormal;
|
||||||
|
leftBalance.Text = UpgradeStore.FormatCurrency(targetWallet.Balance);
|
||||||
|
leftBalance.TextColor = GUIStyle.TextColorNormal;
|
||||||
|
}
|
||||||
|
else if (isSending)
|
||||||
|
{
|
||||||
|
rightBalance.Text = UpgradeStore.FormatCurrency(otherWallet.Balance + transferAmountInput.IntValue);
|
||||||
|
rightBalance.TextColor = GUIStyle.Blue;
|
||||||
|
leftBalance.Text = UpgradeStore.FormatCurrency(targetWallet.Balance - transferAmountInput.IntValue);
|
||||||
|
leftBalance.TextColor = GUIStyle.Red;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rightBalance.Text = UpgradeStore.FormatCurrency(otherWallet.Balance - transferAmountInput.IntValue);
|
||||||
|
rightBalance.TextColor = GUIStyle.Red;
|
||||||
|
leftBalance.Text = UpgradeStore.FormatCurrency(targetWallet.Balance + transferAmountInput.IntValue);
|
||||||
|
leftBalance.TextColor = GUIStyle.Blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateMaxInput()
|
||||||
|
{
|
||||||
|
transferAmountInput.MaxValueInt = isSending ? targetWallet.Balance : otherWallet.Balance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ToggleTransferMenuIcon(GUIButton btn, bool open)
|
||||||
|
{
|
||||||
|
foreach (GUIComponent child in btn.Children)
|
||||||
|
{
|
||||||
|
child.SpriteEffects = open ? SpriteEffects.None : SpriteEffects.FlipVertically;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ToggleCenterButton(GUIButton btn, bool isSending)
|
||||||
|
{
|
||||||
|
foreach (GUIComponent child in btn.Children)
|
||||||
|
{
|
||||||
|
child.SpriteEffects = isSending ? SpriteEffects.None : SpriteEffects.FlipHorizontally;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SendTransaction(Option<Character> to, Option<Character> from, int amount)
|
||||||
|
{
|
||||||
|
INetSerializableStruct transfer = new NetWalletTransfer
|
||||||
|
{
|
||||||
|
Sender = from.Select(option => option.ID),
|
||||||
|
Receiver = to.Select(option => option.ID),
|
||||||
|
Amount = amount
|
||||||
|
};
|
||||||
|
IWriteMessage msg = new WriteOnlyMessage().WithHeader(ClientPacketHeader.MONEY);
|
||||||
|
transfer.Write(msg);
|
||||||
|
GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetRewardDistribution(Character character, int newValue)
|
||||||
|
{
|
||||||
|
INetSerializableStruct transfer = new NetWalletSalaryUpdate
|
||||||
|
{
|
||||||
|
Target = character.ID,
|
||||||
|
NewRewardDistribution = newValue
|
||||||
|
};
|
||||||
|
IWriteMessage msg = new WriteOnlyMessage().WithHeader(ClientPacketHeader.REWARD_DISTRIBUTION);
|
||||||
|
transfer.Write(msg);
|
||||||
|
GameMain.Client?.ClientPeer?.Send(msg, DeliveryMethod.Reliable);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GetRewardDistributionPercentage(int distribution, ImmutableArray<Character> crew)
|
||||||
|
{
|
||||||
|
return Mission.GetRewardShare(distribution, crew, Option<int>.None()).Percentage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private GUIComponent CreateClientInfoFrame(GUIFrame frame, Client client, Sprite permissionIcon = null)
|
private GUIComponent CreateClientInfoFrame(GUIFrame frame, Client client, Sprite permissionIcon = null)
|
||||||
{
|
{
|
||||||
GUIComponent paddedFrame;
|
GUIComponent paddedFrame;
|
||||||
@@ -1209,8 +1534,6 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private Color unselectedColor = new Color(240, 255, 255, 225);
|
private Color unselectedColor = new Color(240, 255, 255, 225);
|
||||||
private Color selectedColor = new Color(220, 255, 220, 225);
|
|
||||||
private Color ownedColor = new Color(140, 180, 140, 225);
|
|
||||||
private Color unselectableColor = new Color(100, 100, 100, 225);
|
private Color unselectableColor = new Color(100, 100, 100, 225);
|
||||||
private Color pressedColor = new Color(60, 60, 60, 225);
|
private Color pressedColor = new Color(60, 60, 60, 225);
|
||||||
|
|
||||||
@@ -1427,7 +1750,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GUILayoutGroup talentOptionLayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, talentOptionCenterGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
|
GUILayoutGroup talentOptionLayoutGroup = new GUILayoutGroup(new RectTransform(Vector2.One, talentOptionCenterGroup.RectTransform), isHorizontal: true, childAnchor: Anchor.CenterLeft) { Stretch = true };
|
||||||
|
|
||||||
foreach (TalentPrefab talent in talentOption.Talents)
|
foreach (TalentPrefab talent in talentOption.Talents.OrderBy(t => t.Identifier))
|
||||||
{
|
{
|
||||||
GUIFrame talentFrame = new GUIFrame(new RectTransform(Vector2.One, talentOptionLayoutGroup.RectTransform), style: null)
|
GUIFrame talentFrame = new GUIFrame(new RectTransform(Vector2.One, talentOptionLayoutGroup.RectTransform), style: null)
|
||||||
{
|
{
|
||||||
@@ -1652,7 +1975,7 @@ namespace Barotrauma
|
|||||||
controlledCharacter.GiveTalent(talent);
|
controlledCharacter.GiveTalent(talent);
|
||||||
if (GameMain.Client != null)
|
if (GameMain.Client != null)
|
||||||
{
|
{
|
||||||
GameMain.Client.CreateEntityEvent(controlledCharacter, new object[] { NetEntityEvent.Type.UpdateTalents });
|
GameMain.Client.CreateEntityEvent(controlledCharacter, new Character.UpdateTalentsEventData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
selectedTalents = controlledCharacter.Info.GetUnlockedTalentsInTree().ToList();
|
selectedTalents = controlledCharacter.Info.GetUnlockedTalentsInTree().ToList();
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private readonly CampaignUI campaignUI;
|
private readonly CampaignUI campaignUI;
|
||||||
private CampaignMode? Campaign => campaignUI.Campaign;
|
private CampaignMode? Campaign => campaignUI.Campaign;
|
||||||
private int AvailableMoney => Campaign?.Money ?? 0;
|
private Wallet PlayerWallet => Campaign?.Wallet ?? Wallet.Invalid;
|
||||||
private UpgradeTab selectedUpgradeTab = UpgradeTab.Upgrade;
|
private UpgradeTab selectedUpgradeTab = UpgradeTab.Upgrade;
|
||||||
|
|
||||||
private GUIMessageBox? currectConfirmation;
|
private GUIMessageBox? currectConfirmation;
|
||||||
@@ -61,7 +61,7 @@ namespace Barotrauma
|
|||||||
private Vector2[][] subHullVertices = new Vector2[0][];
|
private Vector2[][] subHullVertices = new Vector2[0][];
|
||||||
private List<Structure> submarineWalls = new List<Structure>();
|
private List<Structure> submarineWalls = new List<Structure>();
|
||||||
|
|
||||||
public MapEntity? HoveredItem;
|
public MapEntity? HoveredEntity;
|
||||||
private bool highlightWalls;
|
private bool highlightWalls;
|
||||||
|
|
||||||
private UpgradeCategory? currentUpgradeCategory;
|
private UpgradeCategory? currentUpgradeCategory;
|
||||||
@@ -105,6 +105,7 @@ namespace Barotrauma
|
|||||||
Campaign.UpgradeManager.OnUpgradesChanged += RefreshAll;
|
Campaign.UpgradeManager.OnUpgradesChanged += RefreshAll;
|
||||||
Campaign.CargoManager.OnPurchasedItemsChanged += RefreshAll;
|
Campaign.CargoManager.OnPurchasedItemsChanged += RefreshAll;
|
||||||
Campaign.CargoManager.OnSoldItemsChanged += RefreshAll;
|
Campaign.CargoManager.OnSoldItemsChanged += RefreshAll;
|
||||||
|
Campaign.OnMoneyChanged.RegisterOverwriteExisting(nameof(UpgradeStore).ToIdentifier(), e => { RefreshAll(); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RefreshAll()
|
public void RefreshAll()
|
||||||
@@ -184,7 +185,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset the order first
|
// reset the order first
|
||||||
foreach (UpgradeCategory category in UpgradeCategory.Categories)
|
foreach (UpgradeCategory category in UpgradeCategory.Categories.OrderBy(c => c.Name))
|
||||||
{
|
{
|
||||||
GUIComponent component = categoryList.Content.FindChild(c => c.UserData is CategoryData categoryData && categoryData.Category == category);
|
GUIComponent component = categoryList.Content.FindChild(c => c.UserData is CategoryData categoryData && categoryData.Category == category);
|
||||||
component?.SetAsLastChild();
|
component?.SetAsLastChild();
|
||||||
@@ -286,7 +287,7 @@ namespace Barotrauma
|
|||||||
GUILayoutGroup rightLayout = new GUILayoutGroup(rectT(0.5f, 1, topHeaderLayout), childAnchor: Anchor.TopRight);
|
GUILayoutGroup rightLayout = new GUILayoutGroup(rectT(0.5f, 1, topHeaderLayout), childAnchor: Anchor.TopRight);
|
||||||
GUILayoutGroup priceLayout = new GUILayoutGroup(rectT(1, 0.8f, rightLayout), childAnchor: Anchor.Center) { RelativeSpacing = 0.08f };
|
GUILayoutGroup priceLayout = new GUILayoutGroup(rectT(1, 0.8f, rightLayout), childAnchor: Anchor.Center) { RelativeSpacing = 0.08f };
|
||||||
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.Get("CampaignStore.Balance"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right);
|
new GUITextBlock(rectT(1f, 0f, priceLayout), TextManager.Get("CampaignStore.Balance"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right);
|
||||||
new GUITextBlock(rectT(1f, 0f, priceLayout), FormatCurrency(AvailableMoney, format: true), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right) { TextGetter = () => FormatCurrency(AvailableMoney, format: true) };
|
new GUITextBlock(rectT(1f, 0f, priceLayout), FormatCurrency(PlayerWallet.Balance, format: true), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.Right) { TextGetter = () => FormatCurrency(PlayerWallet.Balance, format: true) };
|
||||||
new GUIFrame(rectT(0.5f, 0.1f, rightLayout, Anchor.BottomRight), style: "HorizontalLine") { IgnoreLayoutGroups = true };
|
new GUIFrame(rectT(0.5f, 0.1f, rightLayout, Anchor.BottomRight), style: "HorizontalLine") { IgnoreLayoutGroups = true };
|
||||||
|
|
||||||
repairButton.OnClicked = upgradeButton.OnClicked = (button, o) =>
|
repairButton.OnClicked = upgradeButton.OnClicked = (button, o) =>
|
||||||
@@ -343,15 +344,15 @@ namespace Barotrauma
|
|||||||
private void DrawItemSwapPreview(SpriteBatch spriteBatch, GUICustomComponent component)
|
private void DrawItemSwapPreview(SpriteBatch spriteBatch, GUICustomComponent component)
|
||||||
{
|
{
|
||||||
var selectedItem = customizeTabOpen ?
|
var selectedItem = customizeTabOpen ?
|
||||||
activeItemSwapSlideDown?.UserData as Item ?? HoveredItem as Item :
|
activeItemSwapSlideDown?.UserData as Item ?? HoveredEntity as Item :
|
||||||
HoveredItem as Item;
|
HoveredEntity as Item;
|
||||||
if (selectedItem?.Prefab.SwappableItem == null) { return; }
|
if (selectedItem?.Prefab.SwappableItem == null) { return; }
|
||||||
|
|
||||||
Sprite schematicsSprite = selectedItem.Prefab.SwappableItem.SchematicSprite;
|
Sprite schematicsSprite = selectedItem.Prefab.SwappableItem.SchematicSprite;
|
||||||
if (schematicsSprite == null) { return; }
|
if (schematicsSprite == null) { return; }
|
||||||
float schematicsScale = Math.Min(component.Rect.Width / 2 / schematicsSprite.size.X, component.Rect.Height / schematicsSprite.size.Y);
|
float schematicsScale = Math.Min(component.Rect.Width / 2 / schematicsSprite.size.X, component.Rect.Height / schematicsSprite.size.Y);
|
||||||
Vector2 center = new Vector2(component.Rect.Center.X, component.Rect.Center.Y);
|
Vector2 center = new Vector2(component.Rect.Center.X, component.Rect.Center.Y);
|
||||||
schematicsSprite.Draw(spriteBatch, new Vector2(component.Rect.X, center.Y), GUIStyle.Green, new Vector2(0, schematicsSprite.size.Y / 2),
|
schematicsSprite.Draw(spriteBatch, new Vector2(component.Rect.X, center.Y), GUIStyle.Green, new Vector2(0, schematicsSprite.size.Y / 2),
|
||||||
scale: schematicsScale);
|
scale: schematicsScale);
|
||||||
|
|
||||||
var swappableItemList = selectedUpgradeCategoryLayout?.FindChild("prefablist", true) as GUIListBox;
|
var swappableItemList = selectedUpgradeCategoryLayout?.FindChild("prefablist", true) as GUIListBox;
|
||||||
@@ -426,14 +427,14 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AvailableMoney >= hullRepairCost)
|
if (PlayerWallet.CanAfford(hullRepairCost))
|
||||||
{
|
{
|
||||||
LocalizedString body = TextManager.GetWithVariable("WallRepairs.PurchasePromptBody", "[amount]", hullRepairCost.ToString());
|
LocalizedString body = TextManager.GetWithVariable("WallRepairs.PurchasePromptBody", "[amount]", hullRepairCost.ToString());
|
||||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
||||||
{
|
{
|
||||||
if (AvailableMoney >= hullRepairCost)
|
if (PlayerWallet.Balance >= hullRepairCost)
|
||||||
{
|
{
|
||||||
Campaign.Money -= hullRepairCost;
|
PlayerWallet.TryDeduct(hullRepairCost);
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
|
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
|
||||||
Campaign.PurchasedHullRepairs = true;
|
Campaign.PurchasedHullRepairs = true;
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
@@ -461,14 +462,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
CreateRepairEntry(currentStoreLayout.Content, TextManager.Get("repairallitems"), "RepairItemsButton", itemRepairCost, (button, o) =>
|
CreateRepairEntry(currentStoreLayout.Content, TextManager.Get("repairallitems"), "RepairItemsButton", itemRepairCost, (button, o) =>
|
||||||
{
|
{
|
||||||
if (AvailableMoney >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
if (PlayerWallet.Balance >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
||||||
{
|
{
|
||||||
LocalizedString body = TextManager.GetWithVariable("ItemRepairs.PurchasePromptBody", "[amount]", itemRepairCost.ToString());
|
LocalizedString body = TextManager.GetWithVariable("ItemRepairs.PurchasePromptBody", "[amount]", itemRepairCost.ToString());
|
||||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
||||||
{
|
{
|
||||||
if (AvailableMoney >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
if (PlayerWallet.Balance >= itemRepairCost && !Campaign.PurchasedItemRepairs)
|
||||||
{
|
{
|
||||||
Campaign.Money -= itemRepairCost;
|
PlayerWallet.TryDeduct(itemRepairCost);
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
|
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
|
||||||
Campaign.PurchasedItemRepairs = true;
|
Campaign.PurchasedItemRepairs = true;
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
@@ -507,14 +508,14 @@ namespace Barotrauma
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AvailableMoney >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
|
if (PlayerWallet.CanAfford(shuttleRetrieveCost) && !Campaign.PurchasedLostShuttles)
|
||||||
{
|
{
|
||||||
LocalizedString body = TextManager.GetWithVariable("ReplaceLostShuttles.PurchasePromptBody", "[amount]", shuttleRetrieveCost.ToString());
|
LocalizedString body = TextManager.GetWithVariable("ReplaceLostShuttles.PurchasePromptBody", "[amount]", shuttleRetrieveCost.ToString());
|
||||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), body, () =>
|
||||||
{
|
{
|
||||||
if (AvailableMoney >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
|
if (PlayerWallet.Balance >= shuttleRetrieveCost && !Campaign.PurchasedLostShuttles)
|
||||||
{
|
{
|
||||||
Campaign.Money -= shuttleRetrieveCost;
|
PlayerWallet.TryDeduct(shuttleRetrieveCost);
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
|
GameAnalyticsManager.AddMoneySpentEvent(hullRepairCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
|
||||||
Campaign.PurchasedLostShuttles = true;
|
Campaign.PurchasedLostShuttles = true;
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
@@ -572,13 +573,13 @@ namespace Barotrauma
|
|||||||
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUIStyle.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
|
new GUITextBlock(rectT(1, 0, textLayout), title, font: GUIStyle.SubHeadingFont) { CanBeFocused = false, AutoScaleHorizontal = true };
|
||||||
new GUITextBlock(rectT(1, 0, textLayout), FormatCurrency(price));
|
new GUITextBlock(rectT(1, 0, textLayout), FormatCurrency(price));
|
||||||
GUILayoutGroup buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, contentLayout), childAnchor: Anchor.Center) { UserData = "buybutton" };
|
GUILayoutGroup buyButtonLayout = new GUILayoutGroup(rectT(0.2f, 1, contentLayout), childAnchor: Anchor.Center) { UserData = "buybutton" };
|
||||||
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = AvailableMoney >= price && !isDisabled, OnClicked = onPressed };
|
new GUIButton(rectT(0.7f, 0.5f, buyButtonLayout), string.Empty, style: "RepairBuyButton") { ClickSound = GUISoundType.HireRepairClick, Enabled = PlayerWallet.Balance >= price && !isDisabled, OnClicked = onPressed };
|
||||||
contentLayout.Recalculate();
|
contentLayout.Recalculate();
|
||||||
buyButtonLayout.Recalculate();
|
buyButtonLayout.Recalculate();
|
||||||
|
|
||||||
if (disableElement)
|
if (disableElement)
|
||||||
{
|
{
|
||||||
frameChild.Enabled = AvailableMoney >= price && !isDisabled;
|
frameChild.Enabled = PlayerWallet.Balance >= price && !isDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HasPermission)
|
if (!HasPermission)
|
||||||
@@ -610,9 +611,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
Dictionary<UpgradeCategory, List<UpgradePrefab>> upgrades = new Dictionary<UpgradeCategory, List<UpgradePrefab>>();
|
Dictionary<UpgradeCategory, List<UpgradePrefab>> upgrades = new Dictionary<UpgradeCategory, List<UpgradePrefab>>();
|
||||||
|
|
||||||
foreach (UpgradeCategory category in UpgradeCategory.Categories)
|
foreach (UpgradeCategory category in UpgradeCategory.Categories.OrderBy(c => c.Name))
|
||||||
{
|
{
|
||||||
foreach (UpgradePrefab prefab in UpgradePrefab.Prefabs)
|
foreach (UpgradePrefab prefab in UpgradePrefab.Prefabs.OrderBy(p => p.Name))
|
||||||
{
|
{
|
||||||
if (prefab.UpgradeCategories.Contains(category))
|
if (prefab.UpgradeCategories.Contains(category))
|
||||||
{
|
{
|
||||||
@@ -963,12 +964,12 @@ namespace Barotrauma
|
|||||||
buttonStyle: isPurchased ? "WeaponInstallButton" : "StoreAddToCrateButton"));
|
buttonStyle: isPurchased ? "WeaponInstallButton" : "StoreAddToCrateButton"));
|
||||||
|
|
||||||
if (!(frames.Last().FindChild(c => c is GUIButton, recursive: true) is GUIButton buyButton)) { continue; }
|
if (!(frames.Last().FindChild(c => c is GUIButton, recursive: true) is GUIButton buyButton)) { continue; }
|
||||||
if (Campaign.Money >= price)
|
if (PlayerWallet.CanAfford(price))
|
||||||
{
|
{
|
||||||
buyButton.Enabled = true;
|
buyButton.Enabled = true;
|
||||||
buyButton.OnClicked += (button, o) =>
|
buyButton.OnClicked += (button, o) =>
|
||||||
{
|
{
|
||||||
LocalizedString promptBody = TextManager.GetWithVariables(isPurchased ? "upgrades.itemswappromptbody" : "upgrades.purchaseitemswappromptbody",
|
LocalizedString promptBody = TextManager.GetWithVariables(isPurchased ? "upgrades.itemswappromptbody" : "upgrades.purchaseitemswappromptbody",
|
||||||
("[itemtoinstall]", replacement.Name),
|
("[itemtoinstall]", replacement.Name),
|
||||||
("[amount]", (replacement.SwappableItem.GetPrice(Campaign?.Map?.CurrentLocation) * linkedItems.Count).ToString()));
|
("[amount]", (replacement.SwappableItem.GetPrice(Campaign?.Map?.CurrentLocation) * linkedItems.Count).ToString()));
|
||||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
|
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
|
||||||
@@ -1183,7 +1184,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
buyButton.OnClicked += (button, o) =>
|
buyButton.OnClicked += (button, o) =>
|
||||||
{
|
{
|
||||||
LocalizedString promptBody = TextManager.GetWithVariables("Upgrades.PurchasePromptBody",
|
LocalizedString promptBody = TextManager.GetWithVariables("Upgrades.PurchasePromptBody",
|
||||||
("[upgradename]", prefab.Name),
|
("[upgradename]", prefab.Name),
|
||||||
("[amount]", prefab.Price.GetBuyprice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation).ToString()));
|
("[amount]", prefab.Price.GetBuyprice(Campaign.UpgradeManager.GetUpgradeLevel(prefab, category), Campaign.Map?.CurrentLocation).ToString()));
|
||||||
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
|
currectConfirmation = EventEditorScreen.AskForConfirmation(TextManager.Get("Upgrades.PurchasePromptTitle"), promptBody, () =>
|
||||||
@@ -1334,16 +1335,16 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (GUI.MouseOn == frame)
|
if (GUI.MouseOn == frame)
|
||||||
{
|
{
|
||||||
if (HoveredItem != item) { CreateItemTooltip(item); }
|
if (HoveredEntity != item) { CreateItemTooltip(item); }
|
||||||
HoveredItem = item;
|
HoveredEntity = item;
|
||||||
if (PlayerInput.PrimaryMouseButtonClicked() && selectedUpgradeTab == UpgradeTab.Upgrade && currentStoreLayout != null)
|
if (PlayerInput.PrimaryMouseButtonClicked() && selectedUpgradeTab == UpgradeTab.Upgrade && currentStoreLayout != null)
|
||||||
{
|
{
|
||||||
if (customizeTabOpen)
|
if (customizeTabOpen)
|
||||||
{
|
{
|
||||||
if (selectedUpgradeCategoryLayout != null)
|
if (selectedUpgradeCategoryLayout != null)
|
||||||
{
|
{
|
||||||
var linkedItems = HoveredItem is Item ? Campaign.UpgradeManager.GetLinkedItemsToSwap((Item)HoveredItem) : new List<Item>();
|
var linkedItems = HoveredEntity is Item hoveredItem ? Campaign.UpgradeManager.GetLinkedItemsToSwap(hoveredItem) : new List<Item>();
|
||||||
if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData as Item == HoveredItem || linkedItems.Contains((Item)c.UserData), recursive: true) is GUIButton itemElement)
|
if (selectedUpgradeCategoryLayout.FindChild(c => c.UserData is Item item && (item == HoveredEntity || linkedItems.Contains(item)), recursive: true) is GUIButton itemElement)
|
||||||
{
|
{
|
||||||
if (!itemElement.Selected) { itemElement.OnClicked(itemElement, itemElement.UserData); }
|
if (!itemElement.Selected) { itemElement.OnClicked(itemElement, itemElement.UserData); }
|
||||||
(itemElement.Parent?.Parent?.Parent as GUIListBox)?.ScrollToElement(itemElement);
|
(itemElement.Parent?.Parent?.Parent as GUIListBox)?.ScrollToElement(itemElement);
|
||||||
@@ -1370,8 +1371,8 @@ namespace Barotrauma
|
|||||||
// use pnpoly algorithm to detect if our mouse is within any of the hull polygons
|
// use pnpoly algorithm to detect if our mouse is within any of the hull polygons
|
||||||
if (subHullVertices.Any(hullVertex => ToolBox.PointIntersectsWithPolygon(PlayerInput.MousePosition, hullVertex)))
|
if (subHullVertices.Any(hullVertex => ToolBox.PointIntersectsWithPolygon(PlayerInput.MousePosition, hullVertex)))
|
||||||
{
|
{
|
||||||
if (HoveredItem != firstStructure && !(firstStructure is null)) { CreateItemTooltip(firstStructure); }
|
if (HoveredEntity != firstStructure && !(firstStructure is null)) { CreateItemTooltip(firstStructure); }
|
||||||
HoveredItem = firstStructure;
|
HoveredEntity = firstStructure;
|
||||||
isMouseOnStructure = true;
|
isMouseOnStructure = true;
|
||||||
GUI.MouseCursor = CursorState.Hand;
|
GUI.MouseCursor = CursorState.Hand;
|
||||||
|
|
||||||
@@ -1382,7 +1383,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isMouseOnStructure) { HoveredItem = null; }
|
if (!isMouseOnStructure) { HoveredEntity = null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// flip the tooltip if it is outside of the screen
|
// flip the tooltip if it is outside of the screen
|
||||||
@@ -1582,12 +1583,12 @@ namespace Barotrauma
|
|||||||
priceLabel.Text = TextManager.Get("Upgrade.MaxedUpgrade");
|
priceLabel.Text = TextManager.Get("Upgrade.MaxedUpgrade");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GUIButton button = buttonParent.GetChild<GUIButton>();
|
GUIButton button = buttonParent.GetChild<GUIButton>();
|
||||||
if (button != null)
|
if (button != null)
|
||||||
{
|
{
|
||||||
button.Enabled = currentLevel < prefab.MaxLevel;
|
button.Enabled = currentLevel < prefab.MaxLevel;
|
||||||
if (WaitForServerUpdate || !campaign.AllowedToManageCampaign() || price > campaign.Money)
|
if (WaitForServerUpdate || !campaign.AllowedToManageCampaign() || !campaign.Wallet.CanAfford(price))
|
||||||
{
|
{
|
||||||
button.Enabled = false;
|
button.Enabled = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
// Exchange money
|
// Exchange money
|
||||||
Location.StoreCurrentBalance -= itemValue;
|
Location.StoreCurrentBalance -= itemValue;
|
||||||
campaign.Money += itemValue;
|
campaign.Wallet.TryDeduct(itemValue);
|
||||||
GameAnalyticsManager.AddMoneyGainedEvent(itemValue, GameAnalyticsManager.MoneySource.Store, item.ItemPrefab.Identifier.Value);
|
GameAnalyticsManager.AddMoneyGainedEvent(itemValue, GameAnalyticsManager.MoneySource.Store, item.ItemPrefab.Identifier.Value);
|
||||||
|
|
||||||
// Remove from the sell crate
|
// Remove from the sell crate
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (crewManager != null)
|
if (crewManager != null)
|
||||||
{
|
{
|
||||||
Order order = new Order(orderPrefab, Identifier.Empty, CharacterInfo.HighestManualOrderPriority, Order.OrderType.Current, null, null, orderGiver: Character.Controlled);
|
Order order = orderPrefab.CreateInstance(OrderPrefab.OrderTargetType.Entity, orderGiver: Character.Controlled);
|
||||||
crewManager.SetCharacterOrder(null, order);
|
crewManager.SetCharacterOrder(null, order);
|
||||||
if (crewManager.IsSinglePlayer) { HumanAIController.ReportProblem(Character.Controlled, order); }
|
if (crewManager.IsSinglePlayer) { HumanAIController.ReportProblem(Character.Controlled, order); }
|
||||||
}
|
}
|
||||||
@@ -290,16 +290,6 @@ namespace Barotrauma
|
|||||||
return crewArea.Rect;
|
return crewArea.Rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Character> GetCharacters()
|
|
||||||
{
|
|
||||||
return characters;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<CharacterInfo> GetCharacterInfos()
|
|
||||||
{
|
|
||||||
return characterInfos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Remove the character from the crew (and crew menus).
|
/// Remove the character from the crew (and crew menus).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -708,7 +698,8 @@ namespace Barotrauma
|
|||||||
List<Character> availableSpeakers = Character.CharacterList.FindAll(c =>
|
List<Character> availableSpeakers = Character.CharacterList.FindAll(c =>
|
||||||
c.AIController is HumanAIController &&
|
c.AIController is HumanAIController &&
|
||||||
!c.IsDead &&
|
!c.IsDead &&
|
||||||
c.SpeechImpediment <= 100.0f);
|
c.SpeechImpediment <= 100.0f &&
|
||||||
|
c.CharacterHealth.GetAllAfflictions(a => a is AfflictionHusk huskInfection && huskInfection.Prefab is AfflictionPrefabHusk { CauseSpeechImpediment: true }).None());
|
||||||
pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers));
|
pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,7 +828,7 @@ namespace Barotrauma
|
|||||||
var orderGiver = order?.OrderGiver;
|
var orderGiver = order?.OrderGiver;
|
||||||
if (IsSinglePlayer)
|
if (IsSinglePlayer)
|
||||||
{
|
{
|
||||||
character.SetOrder(order, speak: orderGiver != character);
|
character.SetOrder(order, isNewOrder, speak: orderGiver != character);
|
||||||
string message = order?.GetChatMessage(character.Name, orderGiver?.CurrentHull?.DisplayName?.Value, givingOrderToSelf: character == orderGiver, orderOption: order?.Option ?? Identifier.Empty, isNewOrder: isNewOrder);
|
string message = order?.GetChatMessage(character.Name, orderGiver?.CurrentHull?.DisplayName?.Value, givingOrderToSelf: character == orderGiver, orderOption: order?.Option ?? Identifier.Empty, isNewOrder: isNewOrder);
|
||||||
orderGiver?.Speak(message);
|
orderGiver?.Speak(message);
|
||||||
}
|
}
|
||||||
@@ -2437,26 +2428,26 @@ namespace Barotrauma
|
|||||||
optionNodes.Add(new OptionNode(node, Keys.D0 + hotkey % 10));
|
optionNodes.Add(new OptionNode(node, Keys.D0 + hotkey % 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// The order giver doesn't need to be set for the Order instances as it will be set when the node button is clicked.
|
||||||
|
/// </remarks>
|
||||||
private void CreateShortcutNodes()
|
private void CreateShortcutNodes()
|
||||||
{
|
{
|
||||||
bool HasAppropriateJobId(Character c, Identifier jobId) => c.Info?.Job != null && c.Info.Job.Prefab.AppropriateOrders.Contains(jobId);
|
if (!(GetTargetSubmarine() is { } sub)) { return; }
|
||||||
bool HasAppropriateJob(Character c, string jobId) => HasAppropriateJobId(c, jobId.ToIdentifier());
|
|
||||||
|
|
||||||
var sub = GetTargetSubmarine();
|
|
||||||
if (sub == null) { return; }
|
|
||||||
shortcutNodes.Clear();
|
shortcutNodes.Clear();
|
||||||
if (CanFitMoreNodes() && sub.GetItems(false).Find(i => i.HasTag("reactor") && i.IsPlayerTeamInteractable)?.GetComponent<Reactor>() is Reactor reactor)
|
var subItems = sub.GetItems(false);
|
||||||
|
if (CanFitMoreNodes() && subItems.Find(i => i.HasTag("reactor") && i.IsPlayerTeamInteractable)?.GetComponent<Reactor>() is Reactor reactor)
|
||||||
{
|
{
|
||||||
float reactorOutput = -reactor.CurrPowerConsumption;
|
float reactorOutput = -reactor.CurrPowerConsumption;
|
||||||
// If player is not an engineer AND the reactor is not powered up AND nobody is using the reactor
|
// If player is not an engineer AND the reactor is not powered up AND nobody is using the reactor
|
||||||
// ---> Create shortcut node for "Operate Reactor" order's "Power Up" option
|
// --> Create shortcut node for "Operate Reactor" order's "Power Up" option
|
||||||
if (ShouldDelegateOrder("operatereactor") && reactorOutput < float.Epsilon && characters.None(c => c.SelectedConstruction == reactor.Item))
|
if (ShouldDelegateOrder("operatereactor") && reactorOutput < float.Epsilon && characters.None(c => c.SelectedConstruction == reactor.Item))
|
||||||
{
|
{
|
||||||
var orderPrefab = OrderPrefab.Prefabs["operatereactor"];
|
var orderPrefab = OrderPrefab.Prefabs["operatereactor"];
|
||||||
var order = new Order(orderPrefab, orderPrefab.Options[0], reactor.Item, reactor, Character.Controlled);
|
var order = new Order(orderPrefab, orderPrefab.Options[0], reactor.Item, reactor);
|
||||||
if (IsNonDuplicateOrder(order))
|
if (IsNonDuplicateOrder(order))
|
||||||
{
|
{
|
||||||
shortcutNodes.Add(CreateOrderOptionNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
AddOrderNode(order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2464,11 +2455,11 @@ namespace Barotrauma
|
|||||||
// If player is not a captain AND nobody is using the nav terminal AND the nav terminal is powered up
|
// If player is not a captain AND nobody is using the nav terminal AND the nav terminal is powered up
|
||||||
// --> Create shortcut node for Steer order
|
// --> Create shortcut node for Steer order
|
||||||
if (CanFitMoreNodes() && ShouldDelegateOrder("steer") && IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["steer"]) &&
|
if (CanFitMoreNodes() && ShouldDelegateOrder("steer") && IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["steer"]) &&
|
||||||
sub.GetItems(false).Find(i => i.HasTag("navterminal") && i.IsPlayerTeamInteractable) is Item nav && characters.None(c => c.SelectedConstruction == nav) &&
|
subItems.Find(i => i.HasTag("navterminal") && i.IsPlayerTeamInteractable) is Item nav && characters.None(c => c.SelectedConstruction == nav) &&
|
||||||
nav.GetComponent<Steering>() is Steering steering && steering.Voltage > steering.MinVoltage)
|
nav.GetComponent<Steering>() is Steering steering && steering.Voltage > steering.MinVoltage)
|
||||||
{
|
{
|
||||||
var order = new Order(OrderPrefab.Prefabs["steer"], steering.Item, steering, Character.Controlled);
|
var order = new Order(OrderPrefab.Prefabs["steer"], steering.Item, steering);
|
||||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
AddOrderNode(order);
|
||||||
}
|
}
|
||||||
// If player is not a security officer AND invaders are reported
|
// If player is not a security officer AND invaders are reported
|
||||||
// --> Create shorcut node for Fight Intruders order
|
// --> Create shorcut node for Fight Intruders order
|
||||||
@@ -2476,8 +2467,7 @@ namespace Barotrauma
|
|||||||
ActiveOrders.Any(o => o.Order.Identifier == "reportintruders") &&
|
ActiveOrders.Any(o => o.Order.Identifier == "reportintruders") &&
|
||||||
IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["fightintruders"]))
|
IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["fightintruders"]))
|
||||||
{
|
{
|
||||||
var order = new Order(OrderPrefab.Prefabs["fightintruders"], null, orderGiver: Character.Controlled);
|
AddOrderNodeWithIdentifier("fightintruders");
|
||||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
|
||||||
}
|
}
|
||||||
// If player is not a mechanic AND a breach has been reported
|
// If player is not a mechanic AND a breach has been reported
|
||||||
// --> Create shorcut node for Fix Leaks order
|
// --> Create shorcut node for Fix Leaks order
|
||||||
@@ -2485,8 +2475,7 @@ namespace Barotrauma
|
|||||||
IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["fixleaks"]) &&
|
IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["fixleaks"]) &&
|
||||||
ActiveOrders.Any(o => o.Order.Identifier == "reportbreach"))
|
ActiveOrders.Any(o => o.Order.Identifier == "reportbreach"))
|
||||||
{
|
{
|
||||||
var order = new Order(OrderPrefab.Prefabs["fixleaks"], null, orderGiver: Character.Controlled);
|
AddOrderNodeWithIdentifier("fixleaks");
|
||||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
|
||||||
}
|
}
|
||||||
// --> Create shortcut nodes for the Repair orders
|
// --> Create shortcut nodes for the Repair orders
|
||||||
if (CanFitMoreNodes() && ActiveOrders.Any(o => o.Order.Identifier == "reportbrokendevices"))
|
if (CanFitMoreNodes() && ActiveOrders.Any(o => o.Order.Identifier == "reportbrokendevices"))
|
||||||
@@ -2494,33 +2483,27 @@ namespace Barotrauma
|
|||||||
var reportBrokenDevices = OrderPrefab.Prefabs["reportbrokendevices"];
|
var reportBrokenDevices = OrderPrefab.Prefabs["reportbrokendevices"];
|
||||||
// TODO: Doesn't work for player issued reports, because they don't have a target.
|
// TODO: Doesn't work for player issued reports, because they don't have a target.
|
||||||
bool useSpecificRepairOrder = false;
|
bool useSpecificRepairOrder = false;
|
||||||
string tag = "repairelectrical";
|
if (CanFitMoreNodes() && ShouldDelegateOrder("repairelectrical") &&
|
||||||
if (CanFitMoreNodes() && ShouldDelegateOrder(tag) &&
|
|
||||||
ActiveOrders.Any(o => o.Order.Prefab == reportBrokenDevices && o.Order.TargetItemComponent is Repairable r && r.requiredSkills.Any(s => s.Identifier == "electrical")))
|
ActiveOrders.Any(o => o.Order.Prefab == reportBrokenDevices && o.Order.TargetItemComponent is Repairable r && r.requiredSkills.Any(s => s.Identifier == "electrical")))
|
||||||
{
|
{
|
||||||
if (IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs[tag]))
|
if (IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["repairelectrical"]))
|
||||||
{
|
{
|
||||||
var order = new Order(OrderPrefab.Prefabs[tag], null, orderGiver: Character.Controlled);
|
AddOrderNodeWithIdentifier("repairelectrical");
|
||||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
|
||||||
}
|
}
|
||||||
useSpecificRepairOrder = true;
|
useSpecificRepairOrder = true;
|
||||||
}
|
}
|
||||||
tag = "repairmechanical";
|
if (CanFitMoreNodes() && ShouldDelegateOrder("repairmechanical") &&
|
||||||
if (CanFitMoreNodes() && ShouldDelegateOrder(tag) &&
|
|
||||||
ActiveOrders.Any(o => o.Order.Prefab == reportBrokenDevices && o.Order.TargetItemComponent is Repairable r && r.requiredSkills.Any(s => s.Identifier == "mechanical")))
|
ActiveOrders.Any(o => o.Order.Prefab == reportBrokenDevices && o.Order.TargetItemComponent is Repairable r && r.requiredSkills.Any(s => s.Identifier == "mechanical")))
|
||||||
{
|
{
|
||||||
if (IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs[tag]))
|
if (IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["repairmechanical"]))
|
||||||
{
|
{
|
||||||
var order = new Order(OrderPrefab.Prefabs[tag], null, orderGiver: Character.Controlled);
|
AddOrderNodeWithIdentifier("repairmechanical");
|
||||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
|
||||||
}
|
}
|
||||||
useSpecificRepairOrder = true;
|
useSpecificRepairOrder = true;
|
||||||
}
|
}
|
||||||
tag = "repairsystems";
|
if (!useSpecificRepairOrder && CanFitMoreNodes() && ShouldDelegateOrder("repairsystems") && OrderPrefab.Prefabs["repairsystems"] is OrderPrefab repairOrder && IsNonDuplicateOrderPrefab(repairOrder))
|
||||||
if (!useSpecificRepairOrder && CanFitMoreNodes() && ShouldDelegateOrder(tag) && OrderPrefab.Prefabs[tag] is OrderPrefab repairOrder && IsNonDuplicateOrderPrefab(repairOrder))
|
|
||||||
{
|
{
|
||||||
var order = new Order(OrderPrefab.Prefabs[tag], null, orderGiver: Character.Controlled);
|
AddOrderNodeWithIdentifier("repairsystems");
|
||||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If fire is reported
|
// If fire is reported
|
||||||
@@ -2528,8 +2511,7 @@ namespace Barotrauma
|
|||||||
if (CanFitMoreNodes() && IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["extinguishfires"]) &&
|
if (CanFitMoreNodes() && IsNonDuplicateOrderPrefab(OrderPrefab.Prefabs["extinguishfires"]) &&
|
||||||
ActiveOrders.Any(o => o.Order.Identifier == "reportfire"))
|
ActiveOrders.Any(o => o.Order.Identifier == "reportfire"))
|
||||||
{
|
{
|
||||||
var order = new Order(OrderPrefab.Prefabs["extinguishfires"], null, orderGiver: Character.Controlled);
|
AddOrderNodeWithIdentifier("extinguishfires");
|
||||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
|
||||||
}
|
}
|
||||||
if (CanFitMoreNodes() && characterContext?.Info?.Job?.Prefab?.AppropriateOrders != null)
|
if (CanFitMoreNodes() && characterContext?.Info?.Job?.Prefab?.AppropriateOrders != null)
|
||||||
{
|
{
|
||||||
@@ -2541,8 +2523,8 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!orderPrefab.MustSetTarget || orderPrefab.GetMatchingItems(sub, true, interactableFor: characterContext ?? Character.Controlled).Any())
|
if (!orderPrefab.MustSetTarget || orderPrefab.GetMatchingItems(sub, true, interactableFor: characterContext ?? Character.Controlled).Any())
|
||||||
{
|
{
|
||||||
var order = new Order(orderPrefab, null, orderGiver: Character.Controlled);
|
var order = orderPrefab.CreateInstance(OrderPrefab.OrderTargetType.Entity);
|
||||||
shortcutNodes.Add(CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
AddOrderNode(order);
|
||||||
}
|
}
|
||||||
if (!CanFitMoreNodes()) { break; }
|
if (!CanFitMoreNodes()) { break; }
|
||||||
}
|
}
|
||||||
@@ -2550,9 +2532,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (CanFitMoreNodes() && characterContext != null && !characterContext.IsDismissed)
|
if (CanFitMoreNodes() && characterContext != null && !characterContext.IsDismissed)
|
||||||
{
|
{
|
||||||
var order = new Order(OrderPrefab.Dismissal, null, orderGiver: Character.Controlled);
|
var order = OrderPrefab.Dismissal.CreateInstance(OrderPrefab.OrderTargetType.Entity);
|
||||||
shortcutNodes.Add(
|
AddOrderNode(order);
|
||||||
CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1));
|
|
||||||
}
|
}
|
||||||
shortcutNodes.RemoveAll(n => n.UserData is Order o && !IsOrderAvailable(o));
|
shortcutNodes.RemoveAll(n => n.UserData is Order o && !IsOrderAvailable(o));
|
||||||
if (shortcutNodes.Count < 1) { return; }
|
if (shortcutNodes.Count < 1) { return; }
|
||||||
@@ -2593,18 +2574,30 @@ namespace Barotrauma
|
|||||||
characterContext.CurrentOrders.None(oi => oi?.Identifier == orderPrefab?.Identifier) :
|
characterContext.CurrentOrders.None(oi => oi?.Identifier == orderPrefab?.Identifier) :
|
||||||
characterContext.CurrentOrders.None(oi => oi?.Identifier == orderPrefab?.Identifier && oi.Option == option));
|
characterContext.CurrentOrders.None(oi => oi?.Identifier == orderPrefab?.Identifier && oi.Option == option));
|
||||||
}
|
}
|
||||||
|
void AddOrderNodeWithIdentifier(string identifier)
|
||||||
|
{
|
||||||
|
var order = OrderPrefab.Prefabs[identifier].CreateInstance(OrderPrefab.OrderTargetType.Entity);
|
||||||
|
AddOrderNode(order);
|
||||||
|
}
|
||||||
|
void AddOrderNode(Order order)
|
||||||
|
{
|
||||||
|
var node = order.Option.IsEmpty ?
|
||||||
|
CreateOrderNode(shortcutNodeSize, null, Point.Zero, order, -1) :
|
||||||
|
CreateOrderOptionNode(shortcutNodeSize, null, Point.Zero, order, -1);
|
||||||
|
shortcutNodes.Add(node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateOrderNodes(OrderCategory orderCategory)
|
private void CreateOrderNodes(OrderCategory orderCategory)
|
||||||
{
|
{
|
||||||
var orderPrefabs = OrderPrefab.Prefabs.Where(o => o.Category == orderCategory && !o.IsReport && IsOrderAvailable(o)).ToArray();
|
var orderPrefabs = OrderPrefab.Prefabs.Where(o => o.Category == orderCategory && !o.IsReport && IsOrderAvailable(o)).OrderBy(o => o.Identifier).ToArray();
|
||||||
Order order;
|
Order order;
|
||||||
bool disableNode;
|
bool disableNode;
|
||||||
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance,
|
var offsets = MathUtils.GetPointsOnCircumference(Vector2.Zero, nodeDistance,
|
||||||
GetCircumferencePointCount(orderPrefabs.Length), GetFirstNodeAngle(orderPrefabs.Length));
|
GetCircumferencePointCount(orderPrefabs.Length), GetFirstNodeAngle(orderPrefabs.Length));
|
||||||
for (int i = 0; i < orderPrefabs.Length; i++)
|
for (int i = 0; i < orderPrefabs.Length; i++)
|
||||||
{
|
{
|
||||||
order = new Order(orderPrefabs[i], null, orderGiver: Character.Controlled);
|
order = orderPrefabs[i].CreateInstance(OrderPrefab.OrderTargetType.Entity);
|
||||||
disableNode = !CanCharacterBeHeard() ||
|
disableNode = !CanCharacterBeHeard() ||
|
||||||
(order.MustSetTarget && (order.ItemComponentType != null || order.GetTargetItems().Any() || order.RequireItems.Any()) &&
|
(order.MustSetTarget && (order.ItemComponentType != null || order.GetTargetItems().Any() || order.RequireItems.Any()) &&
|
||||||
order.GetMatchingItems(true, interactableFor: characterContext ?? Character.Controlled).None());
|
order.GetMatchingItems(true, interactableFor: characterContext ?? Character.Controlled).None());
|
||||||
@@ -2617,11 +2610,13 @@ namespace Barotrauma
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create order nodes based on the item context
|
/// Create order nodes based on the item context
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The order giver doesn't need to be set for the Order instances as it will be set when the node button is clicked.
|
||||||
|
/// </remarks>
|
||||||
private void CreateContextualOrderNodes()
|
private void CreateContextualOrderNodes()
|
||||||
{
|
{
|
||||||
if (contextualOrders.None())
|
if (contextualOrders.None())
|
||||||
{
|
{
|
||||||
string orderIdentifier;
|
|
||||||
// Check if targeting an item or a hull
|
// Check if targeting an item or a hull
|
||||||
if (itemContext != null && itemContext.IsPlayerTeamInteractable)
|
if (itemContext != null && itemContext.IsPlayerTeamInteractable)
|
||||||
{
|
{
|
||||||
@@ -2636,66 +2631,62 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (p.TargetItemsMatchItem(itemContext, option))
|
if (p.TargetItemsMatchItem(itemContext, option))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(p, itemContext, targetComponent, Character.Controlled).WithOption(option));
|
contextualOrders.Add(new Order(p, option, itemContext, targetComponent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (p.TargetItemsMatchItem(itemContext) || p.TryGetTargetItemComponent(itemContext, out targetComponent))
|
else if (p.TargetItemsMatchItem(itemContext) || p.TryGetTargetItemComponent(itemContext, out targetComponent))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(p.HasOptions ?
|
contextualOrders.Add(p.HasOptions ?
|
||||||
new Order(p, null, orderGiver: Character.Controlled) :
|
p.CreateInstance(OrderPrefab.OrderTargetType.Entity) :
|
||||||
new Order(p, itemContext, targetComponent, Character.Controlled));
|
new Order(p, itemContext, targetComponent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If targeting a periscope connected to a turret, show the 'operateweapons' order
|
// If targeting a periscope connected to a turret, show the 'operateweapons' order
|
||||||
orderIdentifier = "operateweapons";
|
var operateWeaponsPrefab = OrderPrefab.Prefabs["operateweapons"];
|
||||||
var operateWeaponsPrefab = OrderPrefab.Prefabs[orderIdentifier];
|
if (contextualOrders.None(o => o.Identifier == "operateweapons") && itemContext.Components.Any(c => c is Controller))
|
||||||
if (contextualOrders.None(o => o.Identifier == orderIdentifier) && itemContext.Components.Any(c => c is Controller))
|
|
||||||
{
|
{
|
||||||
var turret = itemContext.GetConnectedComponents<Turret>().FirstOrDefault(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item)) ??
|
var turret = itemContext.GetConnectedComponents<Turret>().FirstOrDefault(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item)) ??
|
||||||
itemContext.GetConnectedComponents<Turret>(recursive: true).FirstOrDefault(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item));
|
itemContext.GetConnectedComponents<Turret>(recursive: true).FirstOrDefault(c => operateWeaponsPrefab.TargetItemsMatchItem(c.Item));
|
||||||
if (turret != null)
|
if (turret != null)
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(operateWeaponsPrefab, turret.Item, turret, Character.Controlled));
|
contextualOrders.Add(new Order(operateWeaponsPrefab, turret.Item, turret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If targeting a repairable item with condition below the repair threshold, show the 'repairsystems' order
|
// If targeting a repairable item with condition below the repair threshold, show the 'repairsystems' order
|
||||||
orderIdentifier = "repairsystems";
|
if (contextualOrders.None(order => order.Identifier == "repairsystems") && itemContext.Repairables.Any(r => r.IsBelowRepairThreshold))
|
||||||
if (contextualOrders.None(order => order.Identifier == orderIdentifier) && itemContext.Repairables.Any(r => r.IsBelowRepairThreshold))
|
|
||||||
{
|
{
|
||||||
if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("electrical"))))
|
if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("electrical"))))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs["repairelectrical"], itemContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new Order(OrderPrefab.Prefabs["repairelectrical"], itemContext, targetItem: null));
|
||||||
}
|
}
|
||||||
else if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("mechanical"))))
|
else if (itemContext.Repairables.Any(r => r != null && r.requiredSkills.Any(s => s != null && s.Identifier.Equals("mechanical"))))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs["repairmechanical"], itemContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new Order(OrderPrefab.Prefabs["repairmechanical"], itemContext, targetItem: null));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs[orderIdentifier], itemContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new Order(OrderPrefab.Prefabs["repairsystems"], itemContext, targetItem: null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove the 'pumpwater' order if the target pump is auto-controlled (as it will immediately overwrite the work done by the bot)
|
// Remove the 'pumpwater' order if the target pump is auto-controlled (as it will immediately overwrite the work done by the bot)
|
||||||
orderIdentifier = "pumpwater";
|
if (contextualOrders.FirstOrDefault(order => order.Identifier.Equals("pumpwater")) is Order pumpOrder &&
|
||||||
if (contextualOrders.FirstOrDefault(order => order.Identifier.Equals(orderIdentifier)) is Order pumpOrder &&
|
|
||||||
itemContext.Components.FirstOrDefault(c => c.GetType() == pumpOrder.ItemComponentType) is Pump pump && pump.IsAutoControlled)
|
itemContext.Components.FirstOrDefault(c => c.GetType() == pumpOrder.ItemComponentType) is Pump pump && pump.IsAutoControlled)
|
||||||
{
|
{
|
||||||
contextualOrders.Remove(pumpOrder);
|
contextualOrders.Remove(pumpOrder);
|
||||||
}
|
}
|
||||||
orderIdentifier = "cleanupitems";
|
if (contextualOrders.None(info => info.Identifier.Equals("cleanupitems")))
|
||||||
if (contextualOrders.None(info => info.Identifier.Equals(orderIdentifier)))
|
|
||||||
{
|
{
|
||||||
if (AIObjectiveCleanupItems.IsValidTarget(itemContext, Character.Controlled, checkInventory: false) || AIObjectiveCleanupItems.IsValidContainer(itemContext, Character.Controlled))
|
if (AIObjectiveCleanupItems.IsValidTarget(itemContext, Character.Controlled, checkInventory: false) || AIObjectiveCleanupItems.IsValidContainer(itemContext, Character.Controlled))
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs[orderIdentifier], itemContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new Order(OrderPrefab.Prefabs["cleanupitems"], itemContext, targetItem: null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddIgnoreOrder(itemContext);
|
AddIgnoreOrder(itemContext);
|
||||||
}
|
}
|
||||||
else if (hullContext != null)
|
else if (hullContext != null)
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs["fixleaks"], hullContext, targetItem: null, Character.Controlled));
|
contextualOrders.Add(new Order(OrderPrefab.Prefabs["fixleaks"], hullContext, targetItem: null));
|
||||||
if (wallContext != null)
|
if (wallContext != null)
|
||||||
{
|
{
|
||||||
AddIgnoreOrder(wallContext);
|
AddIgnoreOrder(wallContext);
|
||||||
@@ -2729,26 +2720,23 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
orderIdentifier = "wait";
|
if (contextualOrders.None(order => order.Identifier.Equals("wait")))
|
||||||
if (contextualOrders.None(order => order.Identifier.Equals(orderIdentifier)))
|
|
||||||
{
|
{
|
||||||
Vector2 position = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
Vector2 position = GameMain.GameScreen.Cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||||
Hull hull = Hull.FindHull(position, guess: Character.Controlled?.CurrentHull);
|
Hull hull = Hull.FindHull(position, guess: Character.Controlled?.CurrentHull);
|
||||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs[orderIdentifier], new OrderTarget(position, hull), Character.Controlled));
|
contextualOrders.Add(new Order(OrderPrefab.Prefabs["wait"], new OrderTarget(position, hull)));
|
||||||
}
|
}
|
||||||
if (contextualOrders.None(order => order.Category != OrderCategory.Movement) && characters.Any(c => c != Character.Controlled))
|
if (contextualOrders.None(order => order.Category != OrderCategory.Movement) && characters.Any(c => c != Character.Controlled))
|
||||||
{
|
{
|
||||||
orderIdentifier = "follow";
|
if (contextualOrders.None(order => order.Identifier.Equals("follow")))
|
||||||
if (contextualOrders.None(order => order.Identifier.Equals(orderIdentifier)))
|
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs[orderIdentifier], null, orderGiver: Character.Controlled));
|
contextualOrders.Add(OrderPrefab.Prefabs["follow"].CreateInstance(OrderPrefab.OrderTargetType.Entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Show 'dismiss' order only when there are crew members with active orders
|
// Show 'dismiss' order only when there are crew members with active orders
|
||||||
orderIdentifier = "dismissed";
|
if (contextualOrders.None(order => order.IsDismissal) && characters.Any(c => !c.IsDismissed))
|
||||||
if (contextualOrders.None(order => order.Identifier.Equals(orderIdentifier)) && characters.Any(c => !c.IsDismissed))
|
|
||||||
{
|
{
|
||||||
contextualOrders.Add(new Order(OrderPrefab.Prefabs[orderIdentifier], null, orderGiver: Character.Controlled));
|
contextualOrders.Add(OrderPrefab.Dismissal.CreateInstance(OrderPrefab.OrderTargetType.Entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
contextualOrders.RemoveAll(o => !IsOrderAvailable(o));
|
contextualOrders.RemoveAll(o => !IsOrderAvailable(o));
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
internal partial class Wallet
|
||||||
|
{
|
||||||
|
public bool IsOwnWallet =>
|
||||||
|
GameMain.GameSession?.Campaign switch
|
||||||
|
{
|
||||||
|
null => false,
|
||||||
|
SinglePlayerCampaign spCampaign => this == spCampaign.Bank,
|
||||||
|
MultiPlayerCampaign mpCampaign => this == mpCampaign.PersonalWallet,
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
|
||||||
|
partial void SettingsChanged(Option<int> balanceChanged, Option<int> rewardChanged)
|
||||||
|
{
|
||||||
|
CampaignMode campaign = GameMain.GameSession?.Campaign;
|
||||||
|
WalletChangedData data = new WalletChangedData
|
||||||
|
{
|
||||||
|
BalanceChanged = balanceChanged,
|
||||||
|
RewardDistributionChanged = rewardChanged,
|
||||||
|
};
|
||||||
|
|
||||||
|
campaign?.OnMoneyChanged.Invoke(new WalletChangedEvent(this, data, CreateWalletInfo()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,6 +63,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual Wallet Wallet => GetWallet();
|
||||||
|
|
||||||
public override void ShowStartMessage()
|
public override void ShowStartMessage()
|
||||||
{
|
{
|
||||||
foreach (Mission mission in Missions.ToList())
|
foreach (Mission mission in Missions.ToList())
|
||||||
@@ -310,7 +312,7 @@ namespace Barotrauma
|
|||||||
if (ShowCampaignUI || ForceMapUI)
|
if (ShowCampaignUI || ForceMapUI)
|
||||||
{
|
{
|
||||||
campaignUIContainer?.AddToGUIUpdateList();
|
campaignUIContainer?.AddToGUIUpdateList();
|
||||||
if (CampaignUI?.UpgradeStore?.HoveredItem != null)
|
if (CampaignUI?.UpgradeStore?.HoveredEntity != null)
|
||||||
{
|
{
|
||||||
if (CampaignUI.SelectedTab != InteractionType.Upgrade) { return; }
|
if (CampaignUI.SelectedTab != InteractionType.Upgrade) { return; }
|
||||||
CampaignUI?.UpgradeStore?.ItemInfoFrame.AddToGUIUpdateList(order: 1);
|
CampaignUI?.UpgradeStore?.ItemInfoFrame.AddToGUIUpdateList(order: 1);
|
||||||
|
|||||||
+54
-7
@@ -21,7 +21,7 @@ namespace Barotrauma
|
|||||||
private UInt16 pendingSaveID = 1;
|
private UInt16 pendingSaveID = 1;
|
||||||
public UInt16 PendingSaveID
|
public UInt16 PendingSaveID
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return pendingSaveID;
|
return pendingSaveID;
|
||||||
}
|
}
|
||||||
@@ -34,6 +34,14 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Wallet PersonalWallet => Character.Controlled?.Wallet ?? Wallet.Invalid;
|
||||||
|
public override Wallet Wallet => GetWallet();
|
||||||
|
|
||||||
|
public override Wallet GetWallet(Client client = null)
|
||||||
|
{
|
||||||
|
return PersonalWallet;
|
||||||
|
}
|
||||||
|
|
||||||
public static void StartCampaignSetup(IEnumerable<string> saveFiles)
|
public static void StartCampaignSetup(IEnumerable<string> saveFiles)
|
||||||
{
|
{
|
||||||
var parent = GameMain.NetLobbyScreen.CampaignSetupFrame;
|
var parent = GameMain.NetLobbyScreen.CampaignSetupFrame;
|
||||||
@@ -195,6 +203,11 @@ namespace Barotrauma
|
|||||||
yield return CoroutineStatus.Running;
|
yield return CoroutineStatus.Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GameMain.Client == null)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Failure;
|
||||||
|
}
|
||||||
|
|
||||||
if (GameMain.Client.LateCampaignJoin)
|
if (GameMain.Client.LateCampaignJoin)
|
||||||
{
|
{
|
||||||
GameMain.Client.LateCampaignJoin = false;
|
GameMain.Client.LateCampaignJoin = false;
|
||||||
@@ -618,7 +631,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
bool forceMapUI = msg.ReadBoolean();
|
bool forceMapUI = msg.ReadBoolean();
|
||||||
|
|
||||||
int money = msg.ReadInt32();
|
|
||||||
bool purchasedHullRepairs = msg.ReadBoolean();
|
bool purchasedHullRepairs = msg.ReadBoolean();
|
||||||
bool purchasedItemRepairs = msg.ReadBoolean();
|
bool purchasedItemRepairs = msg.ReadBoolean();
|
||||||
bool purchasedLostShuttles = msg.ReadBoolean();
|
bool purchasedLostShuttles = msg.ReadBoolean();
|
||||||
@@ -812,12 +824,10 @@ namespace Barotrauma
|
|||||||
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
GameMain.NetLobbyScreen.ToggleCampaignMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldRefresh = campaign.Money != money ||
|
bool shouldRefresh = campaign.PurchasedHullRepairs != purchasedHullRepairs ||
|
||||||
campaign.PurchasedHullRepairs != purchasedHullRepairs ||
|
|
||||||
campaign.PurchasedItemRepairs != purchasedItemRepairs ||
|
campaign.PurchasedItemRepairs != purchasedItemRepairs ||
|
||||||
campaign.PurchasedLostShuttles != purchasedLostShuttles;
|
campaign.PurchasedLostShuttles != purchasedLostShuttles;
|
||||||
|
|
||||||
campaign.Money = money;
|
|
||||||
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
campaign.PurchasedHullRepairs = purchasedHullRepairs;
|
||||||
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
campaign.PurchasedItemRepairs = purchasedItemRepairs;
|
||||||
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
campaign.PurchasedLostShuttles = purchasedLostShuttles;
|
||||||
@@ -896,6 +906,43 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClientReadMoney(IReadMessage inc)
|
||||||
|
{
|
||||||
|
NetWalletUpdate update = INetSerializableStruct.Read<NetWalletUpdate>(inc);
|
||||||
|
foreach (NetWalletTransaction transaction in update.Transactions)
|
||||||
|
{
|
||||||
|
WalletInfo info = transaction.Info;
|
||||||
|
switch (transaction.CharacterID)
|
||||||
|
{
|
||||||
|
case Some<ushort> { Value: var charID}:
|
||||||
|
{
|
||||||
|
Character targetCharacter = Character.CharacterList?.FirstOrDefault(c => c.ID == charID);
|
||||||
|
if (targetCharacter is null) { break; }
|
||||||
|
Wallet wallet = targetCharacter.Wallet;
|
||||||
|
|
||||||
|
wallet.Balance = info.Balance;
|
||||||
|
wallet.RewardDistribution = info.RewardDistribution;
|
||||||
|
TryInvokeEvent(wallet, transaction.ChangedData, info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case None<ushort> _:
|
||||||
|
{
|
||||||
|
Bank.Balance = info.Balance;
|
||||||
|
TryInvokeEvent(Bank, transaction.ChangedData, info);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TryInvokeEvent(Wallet wallet, WalletChangedData data, WalletInfo info)
|
||||||
|
{
|
||||||
|
if (data.BalanceChanged.IsSome() || data.RewardDistributionChanged.IsSome())
|
||||||
|
{
|
||||||
|
OnMoneyChanged.Invoke(new WalletChangedEvent(wallet, data, info));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void Save(XElement element)
|
public override void Save(XElement element)
|
||||||
{
|
{
|
||||||
//do nothing, the clients get the save files from the server
|
//do nothing, the clients get the save files from the server
|
||||||
@@ -908,10 +955,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
string gamesessionDocPath = Path.Combine(SaveUtil.TempPath, "gamesession.xml");
|
string gamesessionDocPath = Path.Combine(SaveUtil.TempPath, "gamesession.xml");
|
||||||
XDocument doc = XMLExtensions.TryLoadXml(gamesessionDocPath);
|
XDocument doc = XMLExtensions.TryLoadXml(gamesessionDocPath);
|
||||||
if (doc == null)
|
if (doc == null)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Failed to load the state of a multiplayer campaign. Could not open the file \"{gamesessionDocPath}\".");
|
DebugConsole.ThrowError($"Failed to load the state of a multiplayer campaign. Could not open the file \"{gamesessionDocPath}\".");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Load(doc.Root.Element("MultiPlayerCampaign"));
|
Load(doc.Root.Element("MultiPlayerCampaign"));
|
||||||
GameMain.GameSession.OwnedSubmarines = SaveUtil.LoadOwnedSubmarines(doc, out SubmarineInfo selectedSub);
|
GameMain.GameSession.OwnedSubmarines = SaveUtil.LoadOwnedSubmarines(doc, out SubmarineInfo selectedSub);
|
||||||
|
|||||||
+15
-3
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
using Barotrauma.Networking;
|
||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
@@ -108,6 +109,9 @@ namespace Barotrauma
|
|||||||
case "pets":
|
case "pets":
|
||||||
petsElement = subElement;
|
petsElement = subElement;
|
||||||
break;
|
break;
|
||||||
|
case Wallet.LowerCaseSaveElementName:
|
||||||
|
Bank = new Wallet(subElement);
|
||||||
|
break;
|
||||||
case "stats":
|
case "stats":
|
||||||
LoadStats(subElement);
|
LoadStats(subElement);
|
||||||
break;
|
break;
|
||||||
@@ -121,7 +125,15 @@ namespace Barotrauma
|
|||||||
|
|
||||||
InitUI();
|
InitUI();
|
||||||
|
|
||||||
Money = element.GetAttributeInt("money", 0);
|
int oldMoney = element.GetAttributeInt("money", 0);
|
||||||
|
if (oldMoney > 0)
|
||||||
|
{
|
||||||
|
Bank = new Wallet
|
||||||
|
{
|
||||||
|
Balance = oldMoney
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
PurchasedLostShuttles = element.GetAttributeBool("purchasedlostshuttles", false);
|
PurchasedLostShuttles = element.GetAttributeBool("purchasedlostshuttles", false);
|
||||||
PurchasedHullRepairs = element.GetAttributeBool("purchasedhullrepairs", false);
|
PurchasedHullRepairs = element.GetAttributeBool("purchasedhullrepairs", false);
|
||||||
PurchasedItemRepairs = element.GetAttributeBool("purchaseditemrepairs", false);
|
PurchasedItemRepairs = element.GetAttributeBool("purchaseditemrepairs", false);
|
||||||
@@ -729,7 +741,6 @@ namespace Barotrauma
|
|||||||
public override void Save(XElement element)
|
public override void Save(XElement element)
|
||||||
{
|
{
|
||||||
XElement modeElement = new XElement("SinglePlayerCampaign",
|
XElement modeElement = new XElement("SinglePlayerCampaign",
|
||||||
new XAttribute("money", Money),
|
|
||||||
new XAttribute("purchasedlostshuttles", PurchasedLostShuttles),
|
new XAttribute("purchasedlostshuttles", PurchasedLostShuttles),
|
||||||
new XAttribute("purchasedhullrepairs", PurchasedHullRepairs),
|
new XAttribute("purchasedhullrepairs", PurchasedHullRepairs),
|
||||||
new XAttribute("purchaseditemrepairs", PurchasedItemRepairs),
|
new XAttribute("purchaseditemrepairs", PurchasedItemRepairs),
|
||||||
@@ -756,13 +767,14 @@ namespace Barotrauma
|
|||||||
|
|
||||||
petsElement = new XElement("pets");
|
petsElement = new XElement("pets");
|
||||||
PetBehavior.SavePets(petsElement);
|
PetBehavior.SavePets(petsElement);
|
||||||
modeElement.Add(petsElement);
|
modeElement.Add(petsElement);
|
||||||
|
|
||||||
CrewManager.Save(modeElement);
|
CrewManager.Save(modeElement);
|
||||||
CampaignMetadata.Save(modeElement);
|
CampaignMetadata.Save(modeElement);
|
||||||
Map.Save(modeElement);
|
Map.Save(modeElement);
|
||||||
CargoManager?.SavePurchasedItems(modeElement);
|
CargoManager?.SavePurchasedItems(modeElement);
|
||||||
UpgradeManager?.Save(modeElement);
|
UpgradeManager?.Save(modeElement);
|
||||||
|
modeElement.Add(Bank.Save());
|
||||||
element.Add(modeElement);
|
element.Add(modeElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public TestGameMode(GameModePreset preset) : base(preset)
|
public TestGameMode(GameModePreset preset) : base(preset)
|
||||||
{
|
{
|
||||||
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs.OrderBy(p => p.Identifier))
|
||||||
{
|
{
|
||||||
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
for (int i = 0; i < jobPrefab.InitialCount; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tabMenu.Update();
|
tabMenu.Update(deltaTime);
|
||||||
if ((PlayerInput.KeyHit(InputType.InfoTab) || PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)) &&
|
if ((PlayerInput.KeyHit(InputType.InfoTab) || PlayerInput.KeyHit(Microsoft.Xna.Framework.Input.Keys.Escape)) &&
|
||||||
!(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
|
!(GUI.KeyboardDispatcher.Subscriber is GUITextBox))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -181,6 +181,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnMoneyChanged(WalletChangedEvent e)
|
||||||
|
{
|
||||||
|
if (e.Wallet.IsOwnWallet) { OnUpdate?.Invoke(); }
|
||||||
|
}
|
||||||
|
|
||||||
// if you have more than 5000 ping there are probably more important things to worry about but hey just in case
|
// if you have more than 5000 ping there are probably more important things to worry about but hey just in case
|
||||||
private static DateTimeOffset GetTimeout() => DateTimeOffset.Now.AddSeconds(5).AddMilliseconds(GetPing());
|
private static DateTimeOffset GetTimeout() => DateTimeOffset.Now.AddSeconds(5).AddMilliseconds(GetPing());
|
||||||
|
|
||||||
@@ -241,6 +246,7 @@ namespace Barotrauma
|
|||||||
private void HealRequestReceived(IReadMessage inc)
|
private void HealRequestReceived(IReadMessage inc)
|
||||||
{
|
{
|
||||||
NetHealRequest request = INetSerializableStruct.Read<NetHealRequest>(inc);
|
NetHealRequest request = INetSerializableStruct.Read<NetHealRequest>(inc);
|
||||||
|
|
||||||
if (request.Result == HealRequestResult.Success)
|
if (request.Result == HealRequestResult.Success)
|
||||||
{
|
{
|
||||||
HealAllPending(force: true);
|
HealAllPending(force: true);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -15,7 +16,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private int jobColumnWidth, characterColumnWidth, statusColumnWidth;
|
private int jobColumnWidth, characterColumnWidth, statusColumnWidth;
|
||||||
|
|
||||||
private readonly SubmarineInfo sub;
|
|
||||||
private readonly List<Mission> selectedMissions;
|
private readonly List<Mission> selectedMissions;
|
||||||
private readonly Location startLocation, endLocation;
|
private readonly Location startLocation, endLocation;
|
||||||
|
|
||||||
@@ -30,11 +30,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public GUIComponent Frame { get; private set; }
|
public GUIComponent Frame { get; private set; }
|
||||||
|
|
||||||
|
public RoundSummary(GameMode gameMode, IEnumerable<Mission> selectedMissions, Location startLocation, Location endLocation)
|
||||||
|
|
||||||
public RoundSummary(SubmarineInfo sub, GameMode gameMode, IEnumerable<Mission> selectedMissions, Location startLocation, Location endLocation)
|
|
||||||
{
|
{
|
||||||
this.sub = sub;
|
|
||||||
this.gameMode = gameMode;
|
this.gameMode = gameMode;
|
||||||
this.selectedMissions = selectedMissions.ToList();
|
this.selectedMissions = selectedMissions.ToList();
|
||||||
this.startLocation = startLocation;
|
this.startLocation = startLocation;
|
||||||
@@ -320,6 +317,16 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
LocalizedString rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", reward));
|
LocalizedString rewardText = TextManager.GetWithVariable("currencyformat", "[credits]", string.Format(CultureInfo.InvariantCulture, "{0:N0}", reward));
|
||||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), RichString.Rich(displayedMission.GetMissionRewardText(Submarine.MainSub)));
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), RichString.Rich(displayedMission.GetMissionRewardText(Submarine.MainSub)));
|
||||||
|
if (Character.Controlled is { } controlled)
|
||||||
|
{
|
||||||
|
var (share, percentage) = Mission.GetRewardShare(controlled.Wallet.RewardDistribution, Mission.GetSalaryEligibleCrew(), Option<int>.Some(reward));
|
||||||
|
if (share > 0)
|
||||||
|
{
|
||||||
|
string shareFormatted = string.Format(CultureInfo.InvariantCulture, "{0:N0}", share);
|
||||||
|
RichString yourShareString = RichString.Rich(TextManager.GetWithVariables("crewwallet.missionreward.get", ("[money]", $"{shareFormatted}"), ("[share]", $"{percentage}")));
|
||||||
|
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), missionTextContent.RectTransform), yourShareString);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayedMission != missionsToDisplay.Last())
|
if (displayedMission != missionsToDisplay.Last())
|
||||||
@@ -407,7 +414,7 @@ namespace Barotrauma
|
|||||||
CreatePathUnlockElement(locationFrame, null, startLocation);
|
CreatePathUnlockElement(locationFrame, null, startLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Faction faction in campaignMode.Factions)
|
foreach (Faction faction in campaignMode.Factions.OrderBy(f => f.Prefab.MenuOrder).ThenBy(f => f.Prefab.Name))
|
||||||
{
|
{
|
||||||
float initialReputation = faction.Reputation.Value;
|
float initialReputation = faction.Reputation.Value;
|
||||||
if (initialFactionReputations.ContainsKey(faction))
|
if (initialFactionReputations.ContainsKey(faction))
|
||||||
@@ -728,7 +735,7 @@ namespace Barotrauma
|
|||||||
if (Math.Abs(reputationChange) > 0)
|
if (Math.Abs(reputationChange) > 0)
|
||||||
{
|
{
|
||||||
string changeText = $"{(reputationChange > 0 ? "+" : "") + reputationChange}";
|
string changeText = $"{(reputationChange > 0 ? "+" : "") + reputationChange}";
|
||||||
string colorStr = XMLExtensions.ColorToString(reputationChange > 0 ? GUIStyle.Green : GUIStyle.Red);
|
string colorStr = XMLExtensions.ToStringHex(reputationChange > 0 ? GUIStyle.Green : GUIStyle.Red);
|
||||||
var richText = RichString.Rich($"{reputationText} (‖color:{colorStr}‖{changeText}‖color:end‖)");
|
var richText = RichString.Rich($"{reputationText} (‖color:{colorStr}‖{changeText}‖color:end‖)");
|
||||||
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
|
new GUITextBlock(new RectTransform(new Vector2(0.5f, 1.0f), sliderHolder.RectTransform),
|
||||||
richText,
|
richText,
|
||||||
|
|||||||
@@ -283,9 +283,9 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public override void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
base.ClientRead(type, msg, sendingTime);
|
base.ClientEventRead(msg, sendingTime);
|
||||||
|
|
||||||
bool open = msg.ReadBoolean();
|
bool open = msg.ReadBoolean();
|
||||||
bool broken = msg.ReadBoolean();
|
bool broken = msg.ReadBoolean();
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
CurrPowerConsumption = powerConsumption;
|
CurrPowerConsumption = powerConsumption;
|
||||||
charging = true;
|
charging = true;
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
Tainted = msg.ReadBoolean();
|
Tainted = msg.ReadBoolean();
|
||||||
if (Tainted)
|
if (Tainted)
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private readonly object mutex = new object();
|
private readonly object mutex = new object();
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
Health = msg.ReadRangedSingle(0, MaxHealth, 8);
|
Health = msg.ReadRangedSingle(0, MaxHealth, 8);
|
||||||
int startOffset = msg.ReadRangedInteger(-1, MaximumVines);
|
int startOffset = msg.ReadRangedInteger(-1, MaximumVines);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.Tracing;
|
||||||
|
|
||||||
namespace Barotrauma.Items.Components
|
namespace Barotrauma.Items.Components
|
||||||
{
|
{
|
||||||
@@ -58,18 +59,23 @@ namespace Barotrauma.Items.Components
|
|||||||
GUI.DrawRectangle(spriteBatch, new Vector2(attachPos.X - 2, -attachPos.Y - 2), Vector2.One * 5, GUIStyle.Red, thickness: 3);
|
GUI.DrawRectangle(spriteBatch, new Vector2(attachPos.X - 2, -attachPos.Y - 2), Vector2.One * 5, GUIStyle.Red, thickness: 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public override bool ValidateEventData(NetEntityEvent.IData data)
|
||||||
|
=> TryExtractEventData<EventData>(data, out _);
|
||||||
|
|
||||||
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
if (!attachable || body == null) { return; }
|
if (!attachable || body == null) { return; }
|
||||||
|
|
||||||
|
var eventData = ExtractEventData<EventData>(extraData);
|
||||||
|
|
||||||
Vector2 attachPos = (Vector2)extraData[2];
|
Vector2 attachPos = eventData.AttachPos;
|
||||||
msg.Write(attachPos.X);
|
msg.Write(attachPos.X);
|
||||||
msg.Write(attachPos.Y);
|
msg.Write(attachPos.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public override void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
base.ClientRead(type, msg, sendingTime);
|
base.ClientEventRead(msg, sendingTime);
|
||||||
|
|
||||||
bool readAttachData = msg.ReadBoolean();
|
bool readAttachData = msg.ReadBoolean();
|
||||||
if (!readAttachData) { return; }
|
if (!readAttachData) { return; }
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ namespace Barotrauma.Items.Components
|
|||||||
ContentXElement getElementFromList(List<ContentXElement> list, int index)
|
ContentXElement getElementFromList(List<ContentXElement> list, int index)
|
||||||
=> CharacterInfo.IsValidIndex(index, list)
|
=> CharacterInfo.IsValidIndex(index, list)
|
||||||
? list[index]
|
? list[index]
|
||||||
: characterInfo.GetRandomElement(list);
|
: null;
|
||||||
|
|
||||||
var disguisedHairElement = getElementFromList(disguisedHairs, disguisedHairIndex);
|
var disguisedHairElement = getElementFromList(disguisedHairs, disguisedHairIndex);
|
||||||
var disguisedBeardElement = getElementFromList(disguisedBeards, disguisedBeardIndex);
|
var disguisedBeardElement = getElementFromList(disguisedBeards, disguisedBeardIndex);
|
||||||
|
|||||||
@@ -566,14 +566,14 @@ namespace Barotrauma.Items.Components
|
|||||||
protected virtual void CreateGUI() { }
|
protected virtual void CreateGUI() { }
|
||||||
|
|
||||||
//Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero.
|
//Starts a coroutine that will read the correct state of the component from the NetBuffer when correctionTimer reaches zero.
|
||||||
protected void StartDelayedCorrection(ServerNetObject type, IReadMessage buffer, float sendingTime, bool waitForMidRoundSync = false)
|
protected void StartDelayedCorrection(IReadMessage buffer, float sendingTime, bool waitForMidRoundSync = false)
|
||||||
{
|
{
|
||||||
if (delayedCorrectionCoroutine != null) CoroutineManager.StopCoroutines(delayedCorrectionCoroutine);
|
if (delayedCorrectionCoroutine != null) { CoroutineManager.StopCoroutines(delayedCorrectionCoroutine); }
|
||||||
|
|
||||||
delayedCorrectionCoroutine = CoroutineManager.StartCoroutine(DoDelayedCorrection(type, buffer, sendingTime, waitForMidRoundSync));
|
delayedCorrectionCoroutine = CoroutineManager.StartCoroutine(DoDelayedCorrection(buffer, sendingTime, waitForMidRoundSync));
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<CoroutineStatus> DoDelayedCorrection(ServerNetObject type, IReadMessage buffer, float sendingTime, bool waitForMidRoundSync)
|
private IEnumerable<CoroutineStatus> DoDelayedCorrection(IReadMessage buffer, float sendingTime, bool waitForMidRoundSync)
|
||||||
{
|
{
|
||||||
while (GameMain.Client != null &&
|
while (GameMain.Client != null &&
|
||||||
(correctionTimer > 0.0f || (waitForMidRoundSync && GameMain.Client.MidRoundSyncing)))
|
(correctionTimer > 0.0f || (waitForMidRoundSync && GameMain.Client.MidRoundSyncing)))
|
||||||
@@ -587,7 +587,7 @@ namespace Barotrauma.Items.Components
|
|||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
((IServerSerializable)this).ClientRead(type, buffer, sendingTime);
|
((IServerSerializable)this).ClientEventRead(buffer, sendingTime);
|
||||||
|
|
||||||
correctionTimer = 0.0f;
|
correctionTimer = 0.0f;
|
||||||
delayedCorrectionCoroutine = null;
|
delayedCorrectionCoroutine = null;
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ namespace Barotrauma.Items.Components
|
|||||||
textBlock.DrawManually(spriteBatch);
|
textBlock.DrawManually(spriteBatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
Text = msg.ReadString();
|
Text = msg.ReadString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
partial class LevelResource : ItemComponent, IServerSerializable
|
partial class LevelResource : ItemComponent, IServerSerializable
|
||||||
{
|
{
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
deattachTimer = msg.ReadSingle();
|
deattachTimer = msg.ReadSingle();
|
||||||
if (deattachTimer >= DeattachDuration)
|
if (deattachTimer >= DeattachDuration)
|
||||||
|
|||||||
@@ -56,8 +56,9 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Light.Position = item.DrawPosition;
|
Vector2 pos = item.DrawPosition;
|
||||||
if (item.Submarine != null) { Light.Position -= item.Submarine.DrawPosition; }
|
if (item.Submarine != null) { pos -= item.Submarine.DrawPosition; }
|
||||||
|
Light.Position = pos;
|
||||||
}
|
}
|
||||||
PhysicsBody body = Light.ParentBody;
|
PhysicsBody body = Light.ParentBody;
|
||||||
if (body != null)
|
if (body != null)
|
||||||
@@ -120,7 +121,7 @@ namespace Barotrauma.Items.Components
|
|||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
IsActive = msg.ReadBoolean();
|
IsActive = msg.ReadBoolean();
|
||||||
lastReceivedState = IsActive;
|
lastReceivedState = IsActive;
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
State = msg.ReadBoolean();
|
State = msg.ReadBoolean();
|
||||||
ushort userID = msg.ReadUInt16();
|
ushort userID = msg.ReadUInt16();
|
||||||
|
|||||||
@@ -251,12 +251,12 @@ namespace Barotrauma.Items.Components
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
msg.Write(pendingState);
|
msg.Write(pendingState);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
ushort userID = msg.ReadUInt16();
|
ushort userID = msg.ReadUInt16();
|
||||||
Character user = userID == Entity.NullEntityID ? null : Entity.FindEntityByID(userID) as Character;
|
Character user = userID == Entity.NullEntityID ? null : Entity.FindEntityByID(userID) as Character;
|
||||||
|
|||||||
@@ -156,17 +156,17 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
//targetForce can only be adjusted at 10% intervals -> no need for more accuracy than this
|
//targetForce can only be adjusted at 10% intervals -> no need for more accuracy than this
|
||||||
msg.WriteRangedInteger((int)(targetForce / 10.0f), -10, 10);
|
msg.WriteRangedInteger((int)(targetForce / 10.0f), -10, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
if (correctionTimer > 0.0f)
|
if (correctionTimer > 0.0f)
|
||||||
{
|
{
|
||||||
StartDelayedCorrection(type, msg.ExtractBits(5 + 16), sendingTime);
|
StartDelayedCorrection(msg.ExtractBits(5 + 16), sendingTime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -705,13 +705,13 @@ namespace Barotrauma.Items.Components
|
|||||||
requiredTimeBlock.Text = ToolBox.SecondsToReadableTime(timeUntilReady > 0.0f ? timeUntilReady : requiredTime);
|
requiredTimeBlock.Text = ToolBox.SecondsToReadableTime(timeUntilReady > 0.0f ? timeUntilReady : requiredTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
uint recipeHash = pendingFabricatedItem?.RecipeHash ?? 0;
|
uint recipeHash = pendingFabricatedItem?.RecipeHash ?? 0;
|
||||||
msg.Write(recipeHash);
|
msg.Write(recipeHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
FabricatorState newState = (FabricatorState)msg.ReadByte();
|
FabricatorState newState = (FabricatorState)msg.ReadByte();
|
||||||
float newTimeUntilReady = msg.ReadSingle();
|
float newTimeUntilReady = msg.ReadSingle();
|
||||||
|
|||||||
@@ -216,14 +216,14 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
//flowpercentage can only be adjusted at 10% intervals -> no need for more accuracy than this
|
//flowpercentage can only be adjusted at 10% intervals -> no need for more accuracy than this
|
||||||
msg.WriteRangedInteger((int)(flowPercentage / 10.0f), -10, 10);
|
msg.WriteRangedInteger((int)(flowPercentage / 10.0f), -10, 10);
|
||||||
msg.Write(IsActive);
|
msg.Write(IsActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
int msgStartPos = msg.BitPosition;
|
int msgStartPos = msg.BitPosition;
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
int msgLength = msg.BitPosition - msgStartPos;
|
int msgLength = msg.BitPosition - msgStartPos;
|
||||||
msg.BitPosition = msgStartPos;
|
msg.BitPosition = msgStartPos;
|
||||||
StartDelayedCorrection(type, msg.ExtractBits(msgLength), sendingTime);
|
StartDelayedCorrection(msg.ExtractBits(msgLength), sendingTime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -608,9 +608,10 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
Vector2 pointerPos = pos - new Vector2(0, 30) * scale;
|
Vector2 pointerPos = pos - new Vector2(0, 30) * scale;
|
||||||
|
|
||||||
|
float scaleMultiplier = 0.95f;
|
||||||
if (optimalRangeNormalized.X == optimalRangeNormalized.Y)
|
if (optimalRangeNormalized.X == optimalRangeNormalized.Y)
|
||||||
{
|
{
|
||||||
sectorSprite.Draw(spriteBatch, pointerPos, GUIStyle.Red, MathHelper.PiOver2, scale);
|
sectorSprite.Draw(spriteBatch, pointerPos, GUIStyle.Red, MathHelper.PiOver2, scale * scaleMultiplier);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -619,7 +620,6 @@ namespace Barotrauma.Items.Components
|
|||||||
spriteBatch.GraphicsDevice.ScissorRectangle = new Rectangle(0, 0, GameMain.GraphicsWidth, (int)(pointerPos.Y + (meterSprite.size.Y - meterSprite.Origin.Y) * scale) - 3);
|
spriteBatch.GraphicsDevice.ScissorRectangle = new Rectangle(0, 0, GameMain.GraphicsWidth, (int)(pointerPos.Y + (meterSprite.size.Y - meterSprite.Origin.Y) * scale) - 3);
|
||||||
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
|
spriteBatch.Begin(SpriteSortMode.Deferred, rasterizerState: GameMain.ScissorTestEnable);
|
||||||
|
|
||||||
float scaleMultiplier = 0.95f;
|
|
||||||
sectorSprite.Draw(spriteBatch, pointerPos, optimalRangeColor, MathHelper.PiOver2 + (allowedSectorRad.X + allowedSectorRad.Y) / 2.0f, scale * scaleMultiplier);
|
sectorSprite.Draw(spriteBatch, pointerPos, optimalRangeColor, MathHelper.PiOver2 + (allowedSectorRad.X + allowedSectorRad.Y) / 2.0f, scale * scaleMultiplier);
|
||||||
sectorSprite.Draw(spriteBatch, pointerPos, offRangeColor, optimalSectorRad.X, scale * scaleMultiplier);
|
sectorSprite.Draw(spriteBatch, pointerPos, offRangeColor, optimalSectorRad.X, scale * scaleMultiplier);
|
||||||
sectorSprite.Draw(spriteBatch, pointerPos, warningColor, allowedSectorRad.X, scale * scaleMultiplier);
|
sectorSprite.Draw(spriteBatch, pointerPos, warningColor, allowedSectorRad.X, scale * scaleMultiplier);
|
||||||
@@ -711,7 +711,7 @@ namespace Barotrauma.Items.Components
|
|||||||
tempRangeIndicator?.Remove();
|
tempRangeIndicator?.Remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
msg.Write(autoTemp);
|
msg.Write(autoTemp);
|
||||||
msg.Write(PowerOn);
|
msg.Write(PowerOn);
|
||||||
@@ -721,11 +721,11 @@ namespace Barotrauma.Items.Components
|
|||||||
correctionTimer = CorrectionDelay;
|
correctionTimer = CorrectionDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
if (correctionTimer > 0.0f)
|
if (correctionTimer > 0.0f)
|
||||||
{
|
{
|
||||||
StartDelayedCorrection(type, msg.ExtractBits(1 + 1 + 8 + 8 + 8 + 8), sendingTime);
|
StartDelayedCorrection(msg.ExtractBits(1 + 1 + 8 + 8 + 8 + 8), sendingTime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -766,7 +766,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (activePingsCount == 0) { disruptedDirections.Clear(); }
|
if (activePingsCount == 0) { disruptedDirections.Clear(); }
|
||||||
foreach (AITarget t in AITarget.List)
|
foreach (AITarget t in AITarget.List)
|
||||||
{
|
{
|
||||||
if (t.Entity is Character c && c.Params.HideInSonar) { continue; }
|
if (t.Entity is Character c && !c.IsUnconscious && c.Params.HideInSonar) { continue; }
|
||||||
if (t.SoundRange <= 0.0f || float.IsNaN(t.SoundRange) || float.IsInfinity(t.SoundRange)) { continue; }
|
if (t.SoundRange <= 0.0f || float.IsNaN(t.SoundRange) || float.IsInfinity(t.SoundRange)) { continue; }
|
||||||
|
|
||||||
float distSqr = Vector2.DistanceSquared(t.WorldPosition, transducerCenter);
|
float distSqr = Vector2.DistanceSquared(t.WorldPosition, transducerCenter);
|
||||||
@@ -1264,7 +1264,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
foreach (AITarget aiTarget in AITarget.List)
|
foreach (AITarget aiTarget in AITarget.List)
|
||||||
{
|
{
|
||||||
float disruption = aiTarget.Entity is Character c ? c.Params.SonarDisruption : aiTarget.SonarDisruption;
|
float disruption = aiTarget.Entity is Character c && !c.IsUnconscious ? c.Params.SonarDisruption : aiTarget.SonarDisruption;
|
||||||
if (disruption <= 0.0f || aiTarget.InDetectable) { continue; }
|
if (disruption <= 0.0f || aiTarget.InDetectable) { continue; }
|
||||||
float distSqr = Vector2.DistanceSquared(aiTarget.WorldPosition, pingSource);
|
float distSqr = Vector2.DistanceSquared(aiTarget.WorldPosition, pingSource);
|
||||||
if (distSqr > worldPingRadiusSqr) { continue; }
|
if (distSqr > worldPingRadiusSqr) { continue; }
|
||||||
@@ -1413,7 +1413,7 @@ namespace Barotrauma.Items.Components
|
|||||||
foreach (Character c in Character.CharacterList)
|
foreach (Character c in Character.CharacterList)
|
||||||
{
|
{
|
||||||
if (c.AnimController.CurrentHull != null || !c.Enabled) { continue; }
|
if (c.AnimController.CurrentHull != null || !c.Enabled) { continue; }
|
||||||
if (c.Params.HideInSonar) { continue; }
|
if (!c.IsUnconscious && c.Params.HideInSonar) { continue; }
|
||||||
if (DetectSubmarineWalls && c.AnimController.CurrentHull == null && item.CurrentHull != null) { continue; }
|
if (DetectSubmarineWalls && c.AnimController.CurrentHull == null && item.CurrentHull != null) { continue; }
|
||||||
|
|
||||||
if (c.AnimController.SimplePhysicsEnabled)
|
if (c.AnimController.SimplePhysicsEnabled)
|
||||||
@@ -1742,7 +1742,7 @@ namespace Barotrauma.Items.Components
|
|||||||
MineralClusters = null;
|
MineralClusters = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
msg.Write(currentMode == Mode.Active);
|
msg.Write(currentMode == Mode.Active);
|
||||||
if (currentMode == Mode.Active)
|
if (currentMode == Mode.Active)
|
||||||
@@ -1758,7 +1758,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
int msgStartPos = msg.BitPosition;
|
int msgStartPos = msg.BitPosition;
|
||||||
|
|
||||||
@@ -1782,7 +1782,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
int msgLength = msg.BitPosition - msgStartPos;
|
int msgLength = msg.BitPosition - msgStartPos;
|
||||||
msg.BitPosition = msgStartPos;
|
msg.BitPosition = msgStartPos;
|
||||||
StartDelayedCorrection(type, msg.ExtractBits(msgLength), sendingTime);
|
StartDelayedCorrection(msg.ExtractBits(msgLength), sendingTime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -822,7 +822,7 @@ namespace Barotrauma.Items.Components
|
|||||||
Connection dockingConnection = item.Connections?.FirstOrDefault(c => c.Name == "toggle_docking");
|
Connection dockingConnection = item.Connections?.FirstOrDefault(c => c.Name == "toggle_docking");
|
||||||
if (dockingConnection != null)
|
if (dockingConnection != null)
|
||||||
{
|
{
|
||||||
connectedPorts = item.GetConnectedComponentsRecursive<DockingPort>(dockingConnection, ignoreInactiveRelays: true);
|
connectedPorts = item.GetConnectedComponentsRecursive<DockingPort>(dockingConnection, ignoreInactiveRelays: true, allowTraversingBackwards: false);
|
||||||
}
|
}
|
||||||
checkConnectedPortsTimer = CheckConnectedPortsInterval;
|
checkConnectedPortsTimer = CheckConnectedPortsInterval;
|
||||||
}
|
}
|
||||||
@@ -894,7 +894,7 @@ namespace Barotrauma.Items.Components
|
|||||||
pathFinder = null;
|
pathFinder = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
msg.Write(AutoPilot);
|
msg.Write(AutoPilot);
|
||||||
msg.Write(dockingNetworkMessagePending);
|
msg.Write(dockingNetworkMessagePending);
|
||||||
@@ -921,7 +921,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
int msgStartPos = msg.BitPosition;
|
int msgStartPos = msg.BitPosition;
|
||||||
|
|
||||||
@@ -962,7 +962,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
int msgLength = (int)(msg.BitPosition - msgStartPos);
|
int msgLength = (int)(msg.BitPosition - msgStartPos);
|
||||||
msg.BitPosition = msgStartPos;
|
msg.BitPosition = msgStartPos;
|
||||||
StartDelayedCorrection(type, msg.ExtractBits(msgLength), sendingTime);
|
StartDelayedCorrection(msg.ExtractBits(msgLength), sendingTime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,16 +163,16 @@ namespace Barotrauma.Items.Components
|
|||||||
indicatorSize * item.Scale, Color.Black, depth: item.SpriteDepth - 0.000015f);
|
indicatorSize * item.Scale, Color.Black, depth: item.SpriteDepth - 0.000015f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData)
|
||||||
{
|
{
|
||||||
msg.WriteRangedInteger((int)(rechargeSpeed / MaxRechargeSpeed * 10), 0, 10);
|
msg.WriteRangedInteger((int)(rechargeSpeed / MaxRechargeSpeed * 10), 0, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
if (correctionTimer > 0.0f)
|
if (correctionTimer > 0.0f)
|
||||||
{
|
{
|
||||||
StartDelayedCorrection(type, msg.ExtractBits(4 + 8), sendingTime);
|
StartDelayedCorrection(msg.ExtractBits(4 + 8), sendingTime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
private readonly List<ParticleEmitter> particleEmitters = new List<ParticleEmitter>();
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
bool launch = msg.ReadBoolean();
|
bool launch = msg.ReadBoolean();
|
||||||
if (launch)
|
if (launch)
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ namespace Barotrauma.Items.Components
|
|||||||
item.CreateClientEvent(this);
|
item.CreateClientEvent(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
deteriorationTimer = msg.ReadSingle();
|
deteriorationTimer = msg.ReadSingle();
|
||||||
deteriorateAlwaysResetTimer = msg.ReadSingle();
|
deteriorateAlwaysResetTimer = msg.ReadSingle();
|
||||||
@@ -446,7 +446,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
msg.WriteRangedInteger((int)requestStartFixAction, 0, 2);
|
msg.WriteRangedInteger((int)requestStartFixAction, 0, 2);
|
||||||
msg.Write(qteSuccess);
|
msg.Write(qteSuccess);
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
snapped = msg.ReadBoolean();
|
snapped = msg.ReadBoolean();
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
bool wasScanCompletedPreviously = IsScanCompleted;
|
bool wasScanCompletedPreviously = IsScanCompleted;
|
||||||
scanTimer = msg.ReadSingle();
|
scanTimer = msg.ReadSingle();
|
||||||
|
|||||||
@@ -76,13 +76,14 @@ namespace Barotrauma.Items.Components
|
|||||||
UserData = i,
|
UserData = i,
|
||||||
OnClicked = (button, userData) =>
|
OnClicked = (button, userData) =>
|
||||||
{
|
{
|
||||||
|
int signalIndex = (int)userData;
|
||||||
if (GameMain.IsSingleplayer)
|
if (GameMain.IsSingleplayer)
|
||||||
{
|
{
|
||||||
SendSignal((int)userData, Character.Controlled);
|
SendSignal(signalIndex, Character.Controlled);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
item.CreateClientEvent(this, new object[] { userData });
|
item.CreateClientEvent(this, new EventData(signalIndex));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -104,12 +105,12 @@ namespace Barotrauma.Items.Components
|
|||||||
Container.Inventory.RectTransform = containerHolder.RectTransform;
|
Container.Inventory.RectTransform = containerHolder.RectTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
Write(msg, extraData);
|
Write(msg, extraData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
SendSignal(msg.ReadRangedInteger(0, Signals.Length - 1), sender: null, isServerMessage: true);
|
SendSignal(msg.ReadRangedInteger(0, Signals.Length - 1), sender: null, isServerMessage: true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
if (GameMain.Client.MidRoundSyncing)
|
if (GameMain.Client.MidRoundSyncing)
|
||||||
{
|
{
|
||||||
@@ -161,7 +161,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
int msgLength = (int)(msg.BitPosition - msgStartPos);
|
int msgLength = (int)(msg.BitPosition - msgStartPos);
|
||||||
msg.BitPosition = (int)msgStartPos;
|
msg.BitPosition = (int)msgStartPos;
|
||||||
StartDelayedCorrection(type, msg.ExtractBits(msgLength), sendingTime, waitForMidRoundSync: true);
|
StartDelayedCorrection(msg.ExtractBits(msgLength), sendingTime, waitForMidRoundSync: true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -137,13 +137,14 @@ namespace Barotrauma.Items.Components
|
|||||||
};
|
};
|
||||||
btn.OnClicked += (_, userdata) =>
|
btn.OnClicked += (_, userdata) =>
|
||||||
{
|
{
|
||||||
|
CustomInterfaceElement btnElement = userdata as CustomInterfaceElement;;
|
||||||
if (GameMain.Client == null)
|
if (GameMain.Client == null)
|
||||||
{
|
{
|
||||||
ButtonClicked(userdata as CustomInterfaceElement);
|
ButtonClicked(btnElement);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GameMain.Client.CreateEntityEvent(item, new object[] { NetEntityEvent.Type.ComponentState, item.GetComponentIndex(this), userdata as CustomInterfaceElement });
|
item.CreateClientEvent(this, new EventData(btnElement));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@@ -301,7 +302,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
//extradata contains an array of buttons clicked by the player (or nothing if the player didn't click anything)
|
//extradata contains an array of buttons clicked by the player (or nothing if the player didn't click anything)
|
||||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||||
@@ -323,12 +324,12 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
msg.Write(extraData != null && extraData.Any(d => d as CustomInterfaceElement == customInterfaceElementList[i]));
|
msg.Write(extraData is Item.ComponentStateEventData { ComponentData: EventData eventData } && eventData.BtnElement == customInterfaceElementList[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
partial class MemoryComponent : ItemComponent
|
partial class MemoryComponent : ItemComponent
|
||||||
{
|
{
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
Value = msg.ReadString();
|
Value = msg.ReadString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,16 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
partial class Terminal : ItemComponent, IClientSerializable, IServerSerializable
|
partial class Terminal : ItemComponent, IClientSerializable, IServerSerializable
|
||||||
{
|
{
|
||||||
|
private readonly struct ClientEventData : IEventData
|
||||||
|
{
|
||||||
|
public readonly string Text;
|
||||||
|
|
||||||
|
public ClientEventData(string text)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private GUIListBox historyBox;
|
private GUIListBox historyBox;
|
||||||
private GUITextBlock fillerBlock;
|
private GUITextBlock fillerBlock;
|
||||||
private GUITextBox inputBox;
|
private GUITextBox inputBox;
|
||||||
@@ -42,7 +52,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
item.CreateClientEvent(this, new object[] { text });
|
item.CreateClientEvent(this, new ClientEventData(text));
|
||||||
}
|
}
|
||||||
textBox.Text = string.Empty;
|
textBox.Text = string.Empty;
|
||||||
return true;
|
return true;
|
||||||
@@ -133,17 +143,15 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
if (extraData is null) { return; }
|
if (TryExtractEventData(extraData, out ClientEventData eventData))
|
||||||
|
|
||||||
if (extraData[2] is string str)
|
|
||||||
{
|
{
|
||||||
msg.Write(str);
|
msg.Write(eventData.Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
SendOutput(msg.ReadString());
|
SendOutput(msg.ReadString());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Barotrauma.Items.Components
|
|||||||
ShapeExtensions.DrawCircle(spriteBatch, pos, range, 32, Color.Cyan * 0.5f, 3);
|
ShapeExtensions.DrawCircle(spriteBatch, pos, range, 32, Color.Cyan * 0.5f, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
Channel = msg.ReadRangedInteger(MinChannel, MaxChannel);
|
Channel = msg.ReadRangedInteger(MinChannel, MaxChannel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,16 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
partial class Wire : ItemComponent, IDrawableComponent, IServerSerializable, IClientSerializable
|
partial class Wire : ItemComponent, IDrawableComponent, IServerSerializable, IClientSerializable
|
||||||
{
|
{
|
||||||
|
private readonly struct ClientEventData : IEventData
|
||||||
|
{
|
||||||
|
public readonly int NodeCount;
|
||||||
|
|
||||||
|
public ClientEventData(int nodeCount)
|
||||||
|
{
|
||||||
|
NodeCount = nodeCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Color higlightColor = Color.LightGreen;
|
public static Color higlightColor = Color.LightGreen;
|
||||||
public static Color editorHighlightColor = Color.Yellow;
|
public static Color editorHighlightColor = Color.Yellow;
|
||||||
public static Color editorSelectedColor = Color.Red;
|
public static Color editorSelectedColor = Color.Red;
|
||||||
@@ -555,7 +565,7 @@ namespace Barotrauma.Items.Components
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
int eventIndex = msg.ReadRangedInteger(0, (int)Math.Ceiling(MaxNodeCount / (float)MaxNodesPerNetworkEvent));
|
int eventIndex = msg.ReadRangedInteger(0, (int)Math.Ceiling(MaxNodeCount / (float)MaxNodesPerNetworkEvent));
|
||||||
int nodeCount = msg.ReadRangedInteger(0, MaxNodesPerNetworkEvent);
|
int nodeCount = msg.ReadRangedInteger(0, MaxNodesPerNetworkEvent);
|
||||||
@@ -586,9 +596,13 @@ namespace Barotrauma.Items.Components
|
|||||||
(item.ParentInventory is CharacterInventory characterInventory && ((characterInventory.Owner as Character)?.HasEquippedItem(item) ?? false));
|
(item.ParentInventory is CharacterInventory characterInventory && ((characterInventory.Owner as Character)?.HasEquippedItem(item) ?? false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public override bool ValidateEventData(NetEntityEvent.IData data)
|
||||||
|
=> TryExtractEventData<ClientEventData>(data, out _);
|
||||||
|
|
||||||
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
int nodeCount = (int)extraData[2];
|
var eventData = ExtractEventData<ClientEventData>(extraData);
|
||||||
|
int nodeCount = eventData.NodeCount;
|
||||||
msg.Write((byte)nodeCount);
|
msg.Write((byte)nodeCount);
|
||||||
if (nodeCount > 0)
|
if (nodeCount > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace Barotrauma.Items.Components
|
|||||||
{
|
{
|
||||||
partial class TriggerComponent : ItemComponent, IServerSerializable
|
partial class TriggerComponent : ItemComponent, IServerSerializable
|
||||||
{
|
{
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
CurrentForceFluctuation = msg.ReadRangedSingle(0.0f, 1.0f, 8);
|
CurrentForceFluctuation = msg.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
private readonly Dictionary<string, Widget> widgets = new Dictionary<string, Widget>();
|
private readonly Dictionary<string, Widget> widgets = new Dictionary<string, Widget>();
|
||||||
private float prevAngle;
|
private float prevAngle;
|
||||||
|
|
||||||
|
private float currentBarrelSpin = 0f;
|
||||||
|
|
||||||
private bool flashLowPower;
|
private bool flashLowPower;
|
||||||
private bool flashNoAmmo, flashLoaderBroken;
|
private bool flashNoAmmo, flashLoaderBroken;
|
||||||
private float flashTimer;
|
private float flashTimer;
|
||||||
@@ -716,7 +718,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
UInt16 projectileID = msg.ReadUInt16();
|
UInt16 projectileID = msg.ReadUInt16();
|
||||||
float newTargetRotation = msg.ReadRangedSingle(minRotation, maxRotation, 16);
|
float newTargetRotation = msg.ReadRangedSingle(minRotation, maxRotation, 16);
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ namespace Barotrauma.Items.Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
bool isDocked = msg.ReadBoolean();
|
bool isDocked = msg.ReadBoolean();
|
||||||
|
|
||||||
|
|||||||
@@ -1598,7 +1598,7 @@ namespace Barotrauma
|
|||||||
int maxStackSize = Math.Min(containedItem.Prefab.MaxStackSize, itemContainer.GetMaxStackSize(0));
|
int maxStackSize = Math.Min(containedItem.Prefab.MaxStackSize, itemContainer.GetMaxStackSize(0));
|
||||||
if (maxStackSize > 1 || containedItem.Prefab.HideConditionBar)
|
if (maxStackSize > 1 || containedItem.Prefab.HideConditionBar)
|
||||||
{
|
{
|
||||||
containedState = itemContainer.Inventory.slots[0].ItemCount / (float)maxStackSize;
|
containedState = itemContainer.Inventory.slots[0].Items.Count / (float)maxStackSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1702,7 +1702,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
if (maxStackSize > 1 && inventory != null)
|
if (maxStackSize > 1 && inventory != null)
|
||||||
{
|
{
|
||||||
int itemCount = slot.MouseOn() ? inventory.slots[slotIndex].ItemCount : inventory.slots[slotIndex].Items.Where(it => !DraggingItems.Contains(it)).Count();
|
int itemCount = slot.MouseOn() ? inventory.slots[slotIndex].Items.Count : inventory.slots[slotIndex].Items.Where(it => !DraggingItems.Contains(it)).Count();
|
||||||
if (item.IsFullCondition || MathUtils.NearlyEqual(item.Condition, 0.0f) || itemCount > 1)
|
if (item.IsFullCondition || MathUtils.NearlyEqual(item.Condition, 0.0f) || itemCount > 1)
|
||||||
{
|
{
|
||||||
Vector2 stackCountPos = new Vector2(rect.Right, rect.Bottom);
|
Vector2 stackCountPos = new Vector2(rect.Right, rect.Bottom);
|
||||||
@@ -1795,20 +1795,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
UInt16 lastEventID = msg.ReadUInt16();
|
UInt16 lastEventID = msg.ReadUInt16();
|
||||||
byte slotCount = msg.ReadByte();
|
SharedRead(msg, out receivedItemIDs);
|
||||||
receivedItemIDs = new List<ushort>[slotCount];
|
|
||||||
for (int i = 0; i < slotCount; i++)
|
|
||||||
{
|
|
||||||
receivedItemIDs[i] = new List<ushort>();
|
|
||||||
int itemCount = msg.ReadRangedInteger(0, MaxStackSize);
|
|
||||||
for (int j = 0; j < itemCount; j++)
|
|
||||||
{
|
|
||||||
receivedItemIDs[i].Add(msg.ReadUInt16());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//delay applying the new state if less than 1 second has passed since this client last sent a state to the server
|
//delay applying the new state if less than 1 second has passed since this client last sent a state to the server
|
||||||
//prevents the inventory from briefly reverting to an old state if items are moved around in quick succession
|
//prevents the inventory from briefly reverting to an old state if items are moved around in quick succession
|
||||||
@@ -1895,7 +1885,7 @@ namespace Barotrauma
|
|||||||
receivedItemIDs = null;
|
receivedItemIDs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
SharedWrite(msg, extraData);
|
SharedWrite(msg, extraData);
|
||||||
syncItemsDelay = 1.0f;
|
syncItemsDelay = 1.0f;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Microsoft.Xna.Framework.Graphics;
|
|||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Barotrauma.Extensions;
|
using Barotrauma.Extensions;
|
||||||
using Barotrauma.MapCreatures.Behavior;
|
using Barotrauma.MapCreatures.Behavior;
|
||||||
@@ -1262,25 +1263,19 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
if (type == ServerNetObject.ENTITY_POSITION)
|
EventType eventType =
|
||||||
{
|
(EventType)msg.ReadRangedInteger((int)EventType.MinValue, (int)EventType.MaxValue);
|
||||||
ClientReadPosition(type, msg, sendingTime);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NetEntityEvent.Type eventType =
|
|
||||||
(NetEntityEvent.Type)msg.ReadRangedInteger(0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1);
|
|
||||||
|
|
||||||
switch (eventType)
|
switch (eventType)
|
||||||
{
|
{
|
||||||
case NetEntityEvent.Type.ComponentState:
|
case EventType.ComponentState:
|
||||||
{
|
{
|
||||||
int componentIndex = msg.ReadRangedInteger(0, components.Count - 1);
|
int componentIndex = msg.ReadRangedInteger(0, components.Count - 1);
|
||||||
if (components[componentIndex] is IServerSerializable serverSerializable)
|
if (components[componentIndex] is IServerSerializable serverSerializable)
|
||||||
{
|
{
|
||||||
serverSerializable.ClientRead(type, msg, sendingTime);
|
serverSerializable.ClientEventRead(msg, sendingTime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1288,12 +1283,12 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.InventoryState:
|
case EventType.InventoryState:
|
||||||
{
|
{
|
||||||
int containerIndex = msg.ReadRangedInteger(0, components.Count - 1);
|
int containerIndex = msg.ReadRangedInteger(0, components.Count - 1);
|
||||||
if (components[containerIndex] is ItemContainer container)
|
if (components[containerIndex] is ItemContainer container)
|
||||||
{
|
{
|
||||||
container.Inventory.ClientRead(type, msg, sendingTime);
|
container.Inventory.ClientEventRead(msg, sendingTime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1301,7 +1296,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Status:
|
case EventType.Status:
|
||||||
float prevCondition = condition;
|
float prevCondition = condition;
|
||||||
condition = msg.ReadSingle();
|
condition = msg.ReadSingle();
|
||||||
if (prevCondition > 0.0f && condition <= 0.0f)
|
if (prevCondition > 0.0f && condition <= 0.0f)
|
||||||
@@ -1314,10 +1309,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
SetActiveSprite();
|
SetActiveSprite();
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.AssignCampaignInteraction:
|
case EventType.AssignCampaignInteraction:
|
||||||
CampaignInteractionType = (CampaignMode.InteractionType)msg.ReadByte();
|
CampaignInteractionType = (CampaignMode.InteractionType)msg.ReadByte();
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.ApplyStatusEffect:
|
case EventType.ApplyStatusEffect:
|
||||||
{
|
{
|
||||||
ActionType actionType = (ActionType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ActionType)).Length - 1);
|
ActionType actionType = (ActionType)msg.ReadRangedInteger(0, Enum.GetValues(typeof(ActionType)).Length - 1);
|
||||||
byte componentIndex = msg.ReadByte();
|
byte componentIndex = msg.ReadByte();
|
||||||
@@ -1347,10 +1342,10 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.ChangeProperty:
|
case EventType.ChangeProperty:
|
||||||
ReadPropertyChange(msg, false);
|
ReadPropertyChange(msg, false);
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Upgrade:
|
case EventType.Upgrade:
|
||||||
Identifier identifier = msg.ReadIdentifier();
|
Identifier identifier = msg.ReadIdentifier();
|
||||||
byte level = msg.ReadByte();
|
byte level = msg.ReadByte();
|
||||||
if (UpgradePrefab.Find(identifier) is { } upgradePrefab)
|
if (UpgradePrefab.Find(identifier) is { } upgradePrefab)
|
||||||
@@ -1371,51 +1366,65 @@ namespace Barotrauma
|
|||||||
AddUpgrade(upgrade, false);
|
AddUpgrade(upgrade, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Invalid:
|
default:
|
||||||
break;
|
throw new Exception($"Malformed incoming item event: unsupported event type {eventType}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
if (extraData == null || extraData.Length == 0 || !(extraData[0] is NetEntityEvent.Type))
|
Exception error(string reason)
|
||||||
{
|
{
|
||||||
return;
|
string errorMsg = $"Failed to write a network event for the item \"{Name}\" - {reason}";
|
||||||
|
GameAnalyticsManager.AddErrorEventOnce($"Item.ClientWrite:{Name}", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
|
return new Exception(errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (extraData is null) { throw error("event data was null"); }
|
||||||
|
if (!(extraData is IEventData eventData)) { throw error($"event data was of the wrong type (\"{extraData.GetType().Name}\")"); }
|
||||||
|
|
||||||
NetEntityEvent.Type eventType = (NetEntityEvent.Type)extraData[0];
|
EventType eventType = eventData.EventType;
|
||||||
msg.WriteRangedInteger((int)eventType, 0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1);
|
msg.WriteRangedInteger((int)eventType, (int)EventType.MinValue, (int)EventType.MaxValue);
|
||||||
switch (eventType)
|
switch (eventData)
|
||||||
{
|
{
|
||||||
case NetEntityEvent.Type.ComponentState:
|
case ComponentStateEventData componentStateEventData:
|
||||||
int componentIndex = (int)extraData[1];
|
{
|
||||||
|
var component = componentStateEventData.Component;
|
||||||
|
if (component is null) { throw error("component was null"); }
|
||||||
|
if (!(component is IClientSerializable clientSerializable)) { throw error($"component was not {nameof(IClientSerializable)}"); }
|
||||||
|
int componentIndex = components.IndexOf(component);
|
||||||
|
if (componentIndex < 0) { throw error("component did not belong to item"); }
|
||||||
msg.WriteRangedInteger(componentIndex, 0, components.Count - 1);
|
msg.WriteRangedInteger(componentIndex, 0, components.Count - 1);
|
||||||
(components[componentIndex] as IClientSerializable).ClientWrite(msg, extraData);
|
clientSerializable.ClientEventWrite(msg, extraData);
|
||||||
break;
|
}
|
||||||
case NetEntityEvent.Type.InventoryState:
|
break;
|
||||||
int containerIndex = (int)extraData[1];
|
case InventoryStateEventData inventoryStateEventData:
|
||||||
|
{
|
||||||
|
var container = inventoryStateEventData.Component;
|
||||||
|
if (container is null) { throw error("container was null"); }
|
||||||
|
int containerIndex = components.IndexOf(container);
|
||||||
|
if (containerIndex < 0) { throw error("container did not belong to item"); }
|
||||||
msg.WriteRangedInteger(containerIndex, 0, components.Count - 1);
|
msg.WriteRangedInteger(containerIndex, 0, components.Count - 1);
|
||||||
(components[containerIndex] as ItemContainer).Inventory.ClientWrite(msg, extraData);
|
container.Inventory.ClientEventWrite(msg, extraData);
|
||||||
break;
|
}
|
||||||
case NetEntityEvent.Type.Treatment:
|
break;
|
||||||
UInt16 characterID = (UInt16)extraData[1];
|
case TreatmentEventData treatmentEventData:
|
||||||
Limb targetLimb = (Limb)extraData[2];
|
Character targetCharacter = treatmentEventData.TargetCharacter;
|
||||||
|
|
||||||
Character targetCharacter = FindEntityByID(characterID) as Character;
|
msg.Write(targetCharacter.ID);
|
||||||
|
msg.Write(treatmentEventData.LimbIndex);
|
||||||
msg.Write(characterID);
|
|
||||||
msg.Write(targetCharacter == null ? (byte)255 : (byte)Array.IndexOf(targetCharacter.AnimController.Limbs, targetLimb));
|
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.ChangeProperty:
|
case ChangePropertyEventData changePropertyEventData:
|
||||||
WritePropertyChange(msg, extraData, true);
|
WritePropertyChange(msg, changePropertyEventData, inGameEditableOnly: true);
|
||||||
editingHUDRefreshTimer = 1.0f;
|
editingHUDRefreshTimer = 1.0f;
|
||||||
break;
|
break;
|
||||||
case NetEntityEvent.Type.Combine:
|
case CombineEventData combineEventData:
|
||||||
UInt16 combineTargetID = (UInt16)extraData[1];
|
Item combineTarget = combineEventData.CombineTarget;
|
||||||
msg.Write(combineTargetID);
|
msg.Write(combineTarget.ID);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
throw error($"Unsupported event type {eventData.GetType().Name}");
|
||||||
}
|
}
|
||||||
msg.WritePadBits();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
partial void UpdateNetPosition(float deltaTime)
|
partial void UpdateNetPosition(float deltaTime)
|
||||||
@@ -1451,7 +1460,7 @@ namespace Barotrauma
|
|||||||
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
|
rect.Y = (int)(displayPos.Y + rect.Height / 2.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientReadPosition(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientReadPosition(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
if (body == null)
|
if (body == null)
|
||||||
{
|
{
|
||||||
@@ -1465,7 +1474,7 @@ namespace Barotrauma
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var posInfo = body.ClientRead(type, msg, sendingTime, parentDebugName: Name);
|
var posInfo = body.ClientRead(msg, sendingTime, parentDebugName: Name);
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
if (posInfo != null)
|
if (posInfo != null)
|
||||||
{
|
{
|
||||||
@@ -1510,24 +1519,18 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void CreateClientEvent<T>(T ic) where T : ItemComponent, IClientSerializable
|
public void CreateClientEvent<T>(T ic) where T : ItemComponent, IClientSerializable
|
||||||
|
=> CreateClientEvent(ic, null);
|
||||||
|
|
||||||
|
public void CreateClientEvent<T>(T ic, ItemComponent.IEventData extraData) where T : ItemComponent, IClientSerializable
|
||||||
{
|
{
|
||||||
if (GameMain.Client == null) return;
|
if (GameMain.Client == null) { return; }
|
||||||
|
|
||||||
int index = components.IndexOf(ic);
|
#warning TODO: this should throw an exception
|
||||||
if (index == -1) return;
|
if (!components.Contains(ic)) { return; }
|
||||||
|
|
||||||
GameMain.Client.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ComponentState, index });
|
var eventData = new ComponentStateEventData(ic, extraData);
|
||||||
}
|
if (!ic.ValidateEventData(eventData)) { throw new Exception($"Component event creation failed: {typeof(T).Name}.{nameof(ItemComponent.ValidateEventData)} returned false"); }
|
||||||
|
GameMain.Client.CreateEntityEvent(this, eventData);
|
||||||
public void CreateClientEvent<T>(T ic, object[] extraData) where T : ItemComponent, IClientSerializable
|
|
||||||
{
|
|
||||||
if (GameMain.Client == null) return;
|
|
||||||
|
|
||||||
int index = components.IndexOf(ic);
|
|
||||||
if (index == -1) return;
|
|
||||||
|
|
||||||
object[] data = new object[] { NetEntityEvent.Type.ComponentState, index }.Concat(extraData).ToArray();
|
|
||||||
GameMain.Client.CreateEntityEvent(this, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Item ReadSpawnData(IReadMessage msg, bool spawn = true)
|
public static Item ReadSpawnData(IReadMessage msg, bool spawn = true)
|
||||||
@@ -1576,6 +1579,36 @@ namespace Barotrauma
|
|||||||
bool allowStealing = msg.ReadBoolean();
|
bool allowStealing = msg.ReadBoolean();
|
||||||
int quality = msg.ReadRangedInteger(0, Items.Components.Quality.MaxQuality);
|
int quality = msg.ReadRangedInteger(0, Items.Components.Quality.MaxQuality);
|
||||||
byte teamID = msg.ReadByte();
|
byte teamID = msg.ReadByte();
|
||||||
|
|
||||||
|
bool hasIdCard = msg.ReadBoolean();
|
||||||
|
string ownerName = "", ownerTags = "";
|
||||||
|
int ownerBeardIndex = -1, ownerHairIndex = -1, ownerMoustacheIndex = -1, ownerFaceAttachmentIndex = -1;
|
||||||
|
Color ownerHairColor = Microsoft.Xna.Framework.Color.White,
|
||||||
|
ownerFacialHairColor = Microsoft.Xna.Framework.Color.White,
|
||||||
|
ownerSkinColor = Microsoft.Xna.Framework.Color.White;
|
||||||
|
Identifier ownerJobId = Identifier.Empty;
|
||||||
|
Vector2 ownerSheetIndex = Vector2.Zero;
|
||||||
|
if (hasIdCard)
|
||||||
|
{
|
||||||
|
ownerName = msg.ReadString();
|
||||||
|
ownerTags = msg.ReadString();
|
||||||
|
|
||||||
|
ownerBeardIndex = msg.ReadByte() - 1;
|
||||||
|
ownerHairIndex = msg.ReadByte() - 1;
|
||||||
|
ownerMoustacheIndex = msg.ReadByte() - 1;
|
||||||
|
ownerFaceAttachmentIndex = msg.ReadByte() - 1;
|
||||||
|
|
||||||
|
ownerHairColor = msg.ReadColorR8G8B8();
|
||||||
|
ownerFacialHairColor = msg.ReadColorR8G8B8();
|
||||||
|
ownerSkinColor = msg.ReadColorR8G8B8();
|
||||||
|
|
||||||
|
ownerJobId = msg.ReadIdentifier();
|
||||||
|
|
||||||
|
int x = msg.ReadByte();
|
||||||
|
int y = msg.ReadByte();
|
||||||
|
ownerSheetIndex = (x, y);
|
||||||
|
}
|
||||||
|
|
||||||
bool tagsChanged = msg.ReadBoolean();
|
bool tagsChanged = msg.ReadBoolean();
|
||||||
string tags = "";
|
string tags = "";
|
||||||
if (tagsChanged)
|
if (tagsChanged)
|
||||||
@@ -1587,6 +1620,7 @@ namespace Barotrauma
|
|||||||
tags = string.Join(',',itemPrefab.Tags.Where(t => !removedTags.Contains(t)).Concat(addedTags));
|
tags = string.Join(',',itemPrefab.Tags.Where(t => !removedTags.Contains(t)).Concat(addedTags));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNameTag = msg.ReadBoolean();
|
bool isNameTag = msg.ReadBoolean();
|
||||||
string writtenName = "";
|
string writtenName = "";
|
||||||
if (isNameTag)
|
if (isNameTag)
|
||||||
@@ -1672,6 +1706,17 @@ namespace Barotrauma
|
|||||||
foreach (IdCard idCard in item.GetComponents<IdCard>())
|
foreach (IdCard idCard in item.GetComponents<IdCard>())
|
||||||
{
|
{
|
||||||
idCard.TeamID = (CharacterTeamType)teamID;
|
idCard.TeamID = (CharacterTeamType)teamID;
|
||||||
|
idCard.OwnerName = ownerName;
|
||||||
|
idCard.OwnerTags = ownerTags;
|
||||||
|
idCard.OwnerBeardIndex = ownerBeardIndex;
|
||||||
|
idCard.OwnerHairIndex = ownerHairIndex;
|
||||||
|
idCard.OwnerMoustacheIndex = ownerMoustacheIndex;
|
||||||
|
idCard.OwnerFaceAttachmentIndex = ownerFaceAttachmentIndex;
|
||||||
|
idCard.OwnerHairColor = ownerHairColor;
|
||||||
|
idCard.OwnerFacialHairColor = ownerFacialHairColor;
|
||||||
|
idCard.OwnerSkinColor = ownerSkinColor;
|
||||||
|
idCard.OwnerJobId = ownerJobId;
|
||||||
|
idCard.OwnerSheetIndex = ownerSheetIndex;
|
||||||
}
|
}
|
||||||
if (descriptionChanged) { item.Description = itemDesc; }
|
if (descriptionChanged) { item.Description = itemDesc; }
|
||||||
if (tagsChanged) { item.Tags = tags; }
|
if (tagsChanged) { item.Tags = tags; }
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
partial class Item
|
||||||
|
{
|
||||||
|
private readonly struct CombineEventData : IEventData
|
||||||
|
{
|
||||||
|
public EventType EventType => EventType.Combine;
|
||||||
|
public readonly Item CombineTarget;
|
||||||
|
|
||||||
|
public CombineEventData(Item combineTarget)
|
||||||
|
{
|
||||||
|
CombineTarget = combineTarget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly struct TreatmentEventData : IEventData
|
||||||
|
{
|
||||||
|
public EventType EventType => EventType.Treatment;
|
||||||
|
public readonly Character TargetCharacter;
|
||||||
|
public readonly Limb TargetLimb;
|
||||||
|
public byte LimbIndex
|
||||||
|
=> TargetCharacter?.AnimController?.Limbs is { } limbs
|
||||||
|
? (byte)Array.IndexOf(limbs, TargetLimb)
|
||||||
|
: byte.MaxValue;
|
||||||
|
|
||||||
|
public TreatmentEventData(Character targetCharacter, Limb targetLimb)
|
||||||
|
{
|
||||||
|
TargetCharacter = targetCharacter;
|
||||||
|
TargetLimb = targetLimb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,7 +30,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private float serverUpdateDelay;
|
private float serverUpdateDelay;
|
||||||
private float remoteWaterVolume, remoteOxygenPercentage;
|
private float remoteWaterVolume, remoteOxygenPercentage;
|
||||||
private List<Vector3> remoteFireSources;
|
private NetworkFireSource[] remoteFireSources = null;
|
||||||
private readonly List<BackgroundSection> remoteBackgroundSections = new List<BackgroundSection>();
|
private readonly List<BackgroundSection> remoteBackgroundSections = new List<BackgroundSection>();
|
||||||
private readonly List<RemoteDecal> remoteDecals = new List<RemoteDecal>();
|
private readonly List<RemoteDecal> remoteDecals = new List<RemoteDecal>();
|
||||||
|
|
||||||
@@ -175,15 +175,16 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (!pendingSectionUpdates.Any() && !pendingDecalUpdates.Any())
|
if (!pendingSectionUpdates.Any() && !pendingDecalUpdates.Any())
|
||||||
{
|
{
|
||||||
GameMain.NetworkMember?.CreateEntityEvent(this);
|
GameMain.NetworkMember?.CreateEntityEvent(this, new StatusEventData());
|
||||||
}
|
}
|
||||||
foreach (Decal decal in pendingDecalUpdates)
|
foreach (Decal decal in pendingDecalUpdates)
|
||||||
{
|
{
|
||||||
GameMain.NetworkMember?.CreateEntityEvent(this, new object[] { decal });
|
GameMain.NetworkMember?.CreateEntityEvent(this, new DecalEventData(decal));
|
||||||
}
|
}
|
||||||
|
pendingDecalUpdates.Clear();
|
||||||
foreach (int pendingSectionUpdate in pendingSectionUpdates)
|
foreach (int pendingSectionUpdate in pendingSectionUpdates)
|
||||||
{
|
{
|
||||||
GameMain.NetworkMember?.CreateEntityEvent(this, new object[] { pendingSectionUpdate });
|
GameMain.NetworkMember?.CreateEntityEvent(this, new BackgroundSectionsEventData(pendingSectionUpdate));
|
||||||
}
|
}
|
||||||
pendingSectionUpdates.Clear();
|
pendingSectionUpdates.Clear();
|
||||||
networkUpdatePending = false;
|
networkUpdatePending = false;
|
||||||
@@ -595,132 +596,101 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientWrite(IWriteMessage msg, object[] extraData = null)
|
public void ClientEventWrite(IWriteMessage msg, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
if (extraData == null)
|
if (!(extraData is IEventData eventData)) { throw new Exception($"Malformed hull event: expected {nameof(Hull)}.{nameof(IEventData)}"); }
|
||||||
{
|
|
||||||
msg.WriteRangedInteger(0, 0, 2);
|
|
||||||
msg.WriteRangedSingle(MathHelper.Clamp(waterVolume / Volume, 0.0f, 1.5f), 0.0f, 1.5f, 8);
|
|
||||||
|
|
||||||
msg.Write(FireSources.Count > 0);
|
msg.WriteRangedInteger((int)eventData.EventType, (int)EventType.MinValue, (int)EventType.MaxValue);
|
||||||
if (FireSources.Count > 0)
|
switch (eventData)
|
||||||
{
|
|
||||||
msg.WriteRangedInteger(Math.Min(FireSources.Count, 16), 0, 16);
|
|
||||||
for (int i = 0; i < Math.Min(FireSources.Count, 16); i++)
|
|
||||||
{
|
|
||||||
var fireSource = FireSources[i];
|
|
||||||
Vector2 normalizedPos = new Vector2(
|
|
||||||
(fireSource.Position.X - rect.X) / rect.Width,
|
|
||||||
(fireSource.Position.Y - (rect.Y - rect.Height)) / rect.Height);
|
|
||||||
|
|
||||||
msg.WriteRangedSingle(MathHelper.Clamp(normalizedPos.X, 0.0f, 1.0f), 0.0f, 1.0f, 8);
|
|
||||||
msg.WriteRangedSingle(MathHelper.Clamp(normalizedPos.Y, 0.0f, 1.0f), 0.0f, 1.0f, 8);
|
|
||||||
msg.WriteRangedSingle(MathHelper.Clamp(fireSource.Size.X / rect.Width, 0.0f, 1.0f), 0, 1.0f, 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (extraData[0] is Decal decal)
|
|
||||||
{
|
{
|
||||||
msg.WriteRangedInteger(1, 0, 2);
|
case StatusEventData statusEventData:
|
||||||
int decalIndex = decals.IndexOf(decal);
|
SharedStatusWrite(msg);
|
||||||
msg.Write((byte)(decalIndex < 0 ? 255 : decalIndex));
|
break;
|
||||||
msg.WriteRangedSingle(decal.BaseAlpha, 0.0f, 1.0f, 8);
|
case BackgroundSectionsEventData backgroundSectionsEventData:
|
||||||
}
|
SharedBackgroundSectionsWrite(msg, backgroundSectionsEventData);
|
||||||
else
|
break;
|
||||||
{
|
case DecalEventData decalEventData:
|
||||||
msg.WriteRangedInteger(2, 0, 2);
|
var decal = decalEventData.Decal;
|
||||||
int sectorToUpdate = (int)extraData[0];
|
int decalIndex = decals.IndexOf(decal);
|
||||||
int start = sectorToUpdate * BackgroundSectionsPerNetworkEvent;
|
msg.Write((byte)(decalIndex < 0 ? 255 : decalIndex));
|
||||||
int end = Math.Min((sectorToUpdate + 1) * BackgroundSectionsPerNetworkEvent, BackgroundSections.Count - 1);
|
msg.WriteRangedSingle(decal.BaseAlpha, 0.0f, 1.0f, 8);
|
||||||
msg.WriteRangedInteger(sectorToUpdate, 0, BackgroundSections.Count - 1);
|
break;
|
||||||
for (int i = start; i < end; i++)
|
default:
|
||||||
{
|
throw new Exception($"Malformed hull event: did not expect {eventData.GetType().Name}");
|
||||||
msg.WriteRangedSingle(BackgroundSections[i].ColorStrength, 0.0f, 1.0f, 8);
|
|
||||||
msg.Write(BackgroundSections[i].Color.PackedValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage message, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
bool isBallastFloraUpdate = message.ReadBoolean();
|
EventType eventType = (EventType)msg.ReadRangedInteger((int)EventType.MinValue, (int)EventType.MaxValue);
|
||||||
if (isBallastFloraUpdate)
|
switch (eventType)
|
||||||
{
|
{
|
||||||
BallastFloraBehavior.NetworkHeader header = (BallastFloraBehavior.NetworkHeader) message.ReadByte();
|
case EventType.Status:
|
||||||
if (header == BallastFloraBehavior.NetworkHeader.Spawn)
|
remoteOxygenPercentage = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||||
{
|
|
||||||
Identifier identifier = message.ReadIdentifier();
|
SharedStatusRead(
|
||||||
float x = message.ReadSingle();
|
msg,
|
||||||
float y = message.ReadSingle();
|
out float newWaterVolume,
|
||||||
BallastFlora = new BallastFloraBehavior(this, BallastFloraPrefab.Find(identifier), new Vector2(x, y), firstGrowth: true)
|
out NetworkFireSource[] newFireSources);
|
||||||
{
|
|
||||||
PowerConsumptionTimer = message.ReadSingle()
|
remoteWaterVolume = newWaterVolume;
|
||||||
};
|
remoteFireSources = newFireSources;
|
||||||
}
|
break;
|
||||||
else
|
case EventType.BackgroundSections:
|
||||||
{
|
SharedBackgroundSectionRead(
|
||||||
BallastFlora?.ClientRead(message, header);
|
msg,
|
||||||
}
|
bsnu =>
|
||||||
return;
|
|
||||||
}
|
|
||||||
remoteWaterVolume = message.ReadRangedSingle(0.0f, 1.5f, 8) * Volume;
|
|
||||||
remoteOxygenPercentage = message.ReadRangedSingle(0.0f, 100.0f, 8);
|
|
||||||
|
|
||||||
bool hasFireSources = message.ReadBoolean();
|
|
||||||
remoteFireSources = new List<Vector3>();
|
|
||||||
if (hasFireSources)
|
|
||||||
{
|
|
||||||
int fireSourceCount = message.ReadRangedInteger(0, 16);
|
|
||||||
for (int i = 0; i < fireSourceCount; i++)
|
|
||||||
{
|
|
||||||
remoteFireSources.Add(new Vector3(
|
|
||||||
MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
|
|
||||||
MathHelper.Clamp(message.ReadRangedSingle(0.0f, 1.0f, 8), 0.05f, 0.95f),
|
|
||||||
message.ReadRangedSingle(0.0f, 1.0f, 8)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasExtraData = message.ReadBoolean();
|
|
||||||
if (hasExtraData)
|
|
||||||
{
|
|
||||||
bool hasSectionUpdate = message.ReadBoolean();
|
|
||||||
if (hasSectionUpdate)
|
|
||||||
{
|
|
||||||
int sectorToUpdate = message.ReadRangedInteger(0, BackgroundSections.Count - 1);
|
|
||||||
int start = sectorToUpdate * BackgroundSectionsPerNetworkEvent;
|
|
||||||
int end = Math.Min((sectorToUpdate + 1) * BackgroundSectionsPerNetworkEvent, BackgroundSections.Count - 1);
|
|
||||||
for (int i = start; i < end; i++)
|
|
||||||
{
|
|
||||||
float colorStrength = message.ReadRangedSingle(0.0f, 1.0f, 8);
|
|
||||||
Color color = new Color(message.ReadUInt32());
|
|
||||||
var remoteBackgroundSection = remoteBackgroundSections.Find(s => s.Index == i);
|
|
||||||
if (remoteBackgroundSection != null)
|
|
||||||
{
|
{
|
||||||
remoteBackgroundSection.SetColorStrength(colorStrength);
|
int i = bsnu.SectionIndex;
|
||||||
remoteBackgroundSection.SetColor(color);
|
Color color = bsnu.Color;
|
||||||
}
|
float colorStrength = bsnu.ColorStrength;
|
||||||
else
|
|
||||||
{
|
var remoteBackgroundSection = remoteBackgroundSections.Find(s => s.Index == i);
|
||||||
remoteBackgroundSections.Add(new BackgroundSection(new Rectangle(0, 0, 1, 1), (ushort)i, colorStrength, color, 0));
|
if (remoteBackgroundSection != null)
|
||||||
}
|
{
|
||||||
}
|
remoteBackgroundSection.SetColorStrength(colorStrength);
|
||||||
|
remoteBackgroundSection.SetColor(color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remoteBackgroundSections.Add(new BackgroundSection(new Rectangle(0, 0, 1, 1), (ushort)i, colorStrength, color, 0));
|
||||||
|
}
|
||||||
|
}, out _);
|
||||||
paintAmount = BackgroundSections.Sum(s => s.ColorStrength);
|
paintAmount = BackgroundSections.Sum(s => s.ColorStrength);
|
||||||
}
|
break;
|
||||||
else
|
case EventType.Decal:
|
||||||
{
|
int decalCount = msg.ReadRangedInteger(0, MaxDecalsPerHull);
|
||||||
int decalCount = message.ReadRangedInteger(0, MaxDecalsPerHull);
|
|
||||||
if (decalCount == 0) { decals.Clear(); }
|
if (decalCount == 0) { decals.Clear(); }
|
||||||
remoteDecals.Clear();
|
remoteDecals.Clear();
|
||||||
for (int i = 0; i < decalCount; i++)
|
for (int i = 0; i < decalCount; i++)
|
||||||
{
|
{
|
||||||
UInt32 decalId = message.ReadUInt32();
|
UInt32 decalId = msg.ReadUInt32();
|
||||||
int spriteIndex = message.ReadByte();
|
int spriteIndex = msg.ReadByte();
|
||||||
float normalizedXPos = message.ReadRangedSingle(0.0f, 1.0f, 8);
|
float normalizedXPos = msg.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||||
float normalizedYPos = message.ReadRangedSingle(0.0f, 1.0f, 8);
|
float normalizedYPos = msg.ReadRangedSingle(0.0f, 1.0f, 8);
|
||||||
float decalScale = message.ReadRangedSingle(0.0f, 2.0f, 12);
|
float decalScale = msg.ReadRangedSingle(0.0f, 2.0f, 12);
|
||||||
remoteDecals.Add(new RemoteDecal(decalId, spriteIndex, new Vector2(normalizedXPos, normalizedYPos), decalScale));
|
remoteDecals.Add(new RemoteDecal(decalId, spriteIndex, new Vector2(normalizedXPos, normalizedYPos), decalScale));
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
case EventType.BallastFlora:
|
||||||
|
BallastFloraBehavior.NetworkHeader header = (BallastFloraBehavior.NetworkHeader) msg.ReadByte();
|
||||||
|
if (header == BallastFloraBehavior.NetworkHeader.Spawn)
|
||||||
|
{
|
||||||
|
Identifier identifier = msg.ReadIdentifier();
|
||||||
|
float x = msg.ReadSingle();
|
||||||
|
float y = msg.ReadSingle();
|
||||||
|
BallastFlora = new BallastFloraBehavior(this, BallastFloraPrefab.Find(identifier), new Vector2(x, y), firstGrowth: true)
|
||||||
|
{
|
||||||
|
PowerConsumptionTimer = msg.ReadSingle()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BallastFlora?.ClientRead(msg, header);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception($"Malformed incoming hull event: {eventType} is not a supported event type");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverUpdateDelay > 0.0f) { return; }
|
if (serverUpdateDelay > 0.0f) { return; }
|
||||||
@@ -756,17 +726,15 @@ namespace Barotrauma
|
|||||||
remoteDecals.Clear();
|
remoteDecals.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remoteFireSources == null) { return; }
|
if (remoteFireSources is null) { return; }
|
||||||
|
|
||||||
WaterVolume = remoteWaterVolume;
|
WaterVolume = remoteWaterVolume;
|
||||||
OxygenPercentage = remoteOxygenPercentage;
|
OxygenPercentage = remoteOxygenPercentage;
|
||||||
|
|
||||||
for (int i = 0; i < remoteFireSources.Count; i++)
|
for (int i = 0; i < remoteFireSources.Length; i++)
|
||||||
{
|
{
|
||||||
Vector2 pos = new Vector2(
|
Vector2 pos = remoteFireSources[i].Position;
|
||||||
rect.X + rect.Width * remoteFireSources[i].X,
|
float size = remoteFireSources[i].Size;
|
||||||
rect.Y - rect.Height + (rect.Height * remoteFireSources[i].Y));
|
|
||||||
float size = remoteFireSources[i].Z * rect.Width;
|
|
||||||
|
|
||||||
var newFire = i < FireSources.Count ?
|
var newFire = i < FireSources.Count ?
|
||||||
FireSources[i] :
|
FireSources[i] :
|
||||||
@@ -782,7 +750,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = FireSources.Count - 1; i >= remoteFireSources.Count; i--)
|
for (int i = FireSources.Count - 1; i >= remoteFireSources.Length; i--)
|
||||||
{
|
{
|
||||||
FireSources[i].Remove();
|
FireSources[i].Remove();
|
||||||
if (i < FireSources.Count)
|
if (i < FireSources.Count)
|
||||||
|
|||||||
@@ -121,34 +121,42 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
renderer?.DrawForeground(spriteBatch, cam, LevelObjectManager);
|
renderer?.DrawForeground(spriteBatch, cam, LevelObjectManager);
|
||||||
}
|
}
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
bool isGlobalUpdate = msg.ReadBoolean();
|
EventType eventType = (EventType)msg.ReadByte();
|
||||||
if (isGlobalUpdate)
|
|
||||||
|
switch (eventType)
|
||||||
{
|
{
|
||||||
foreach (LevelWall levelWall in ExtraWalls)
|
case EventType.GlobalDestructibleWall:
|
||||||
{
|
{
|
||||||
if (levelWall.Body.BodyType == BodyType.Static) { continue; }
|
foreach (LevelWall levelWall in ExtraWalls)
|
||||||
|
|
||||||
Vector2 bodyPos = new Vector2(
|
|
||||||
msg.ReadSingle(),
|
|
||||||
msg.ReadSingle());
|
|
||||||
levelWall.MoveState = msg.ReadRangedSingle(0.0f, MathHelper.TwoPi, 16);
|
|
||||||
DestructibleLevelWall destructibleWall = levelWall as DestructibleLevelWall;
|
|
||||||
if (Vector2.DistanceSquared(bodyPos, levelWall.Body.Position) > 0.5f && (destructibleWall == null || !destructibleWall.Destroyed))
|
|
||||||
{
|
{
|
||||||
levelWall.Body.SetTransformIgnoreContacts(ref bodyPos, levelWall.Body.Rotation);
|
if (levelWall.Body.BodyType == BodyType.Static) { continue; }
|
||||||
|
|
||||||
|
Vector2 bodyPos = new Vector2(
|
||||||
|
msg.ReadSingle(),
|
||||||
|
msg.ReadSingle());
|
||||||
|
levelWall.MoveState = msg.ReadRangedSingle(0.0f, MathHelper.TwoPi, 16);
|
||||||
|
if (Vector2.DistanceSquared(bodyPos, levelWall.Body.Position) > 0.5f
|
||||||
|
&& !(levelWall is DestructibleLevelWall { Destroyed: true }))
|
||||||
|
{
|
||||||
|
levelWall.Body.SetTransformIgnoreContacts(ref bodyPos, levelWall.Body.Rotation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else
|
case EventType.SingleDestructibleWall:
|
||||||
{
|
|
||||||
int index = msg.ReadUInt16();
|
|
||||||
byte damageByte = msg.ReadByte();
|
|
||||||
if (index < ExtraWalls.Count && ExtraWalls[index] is DestructibleLevelWall destructibleWall)
|
|
||||||
{
|
{
|
||||||
destructibleWall.SetDamage(destructibleWall.MaxHealth * damageByte / 255.0f);
|
int index = msg.ReadUInt16();
|
||||||
|
float damageByte = msg.ReadByte();
|
||||||
|
if (index < ExtraWalls.Count && ExtraWalls[index] is DestructibleLevelWall destructibleWall)
|
||||||
|
{
|
||||||
|
destructibleWall.SetDamage(destructibleWall.MaxHealth * damageByte / 255.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception($"Malformed incoming level event: {eventType} is not a supported event type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -229,7 +229,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
int objIndex = msg.ReadRangedInteger(0, objects.Count);
|
int objIndex = msg.ReadRangedInteger(0, objects.Count);
|
||||||
objects[objIndex].ClientRead(msg);
|
objects[objIndex].ClientRead(msg);
|
||||||
|
|||||||
@@ -106,7 +106,8 @@ namespace Barotrauma
|
|||||||
WaterEffect.Parameters["xBlurDistance"].SetValue(BlurAmount / 100.0f);
|
WaterEffect.Parameters["xBlurDistance"].SetValue(BlurAmount / 100.0f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ WaterEffect.CurrentTechnique = WaterEffect.Techniques["WaterShader"];
|
{
|
||||||
|
WaterEffect.CurrentTechnique = WaterEffect.Techniques["WaterShader"];
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector2 offset = WavePos;
|
Vector2 offset = WavePos;
|
||||||
|
|||||||
@@ -188,8 +188,10 @@ namespace Barotrauma.Lights
|
|||||||
if (light.ParentBody != null)
|
if (light.ParentBody != null)
|
||||||
{
|
{
|
||||||
light.ParentBody.UpdateDrawPosition();
|
light.ParentBody.UpdateDrawPosition();
|
||||||
light.Position = light.ParentBody.DrawPosition;
|
|
||||||
if (light.ParentSub != null) { light.Position -= light.ParentSub.DrawPosition; }
|
Vector2 pos = light.ParentBody.DrawPosition;
|
||||||
|
if (light.ParentSub != null) { pos -= light.ParentSub.DrawPosition; }
|
||||||
|
light.Position = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
float range = light.LightSourceParams.TextureRange;
|
float range = light.LightSourceParams.TextureRange;
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private (SubmarineInfo pendingSub, float realWorldCrushDepth) pendingSubInfo;
|
private (SubmarineInfo pendingSub, float realWorldCrushDepth) pendingSubInfo;
|
||||||
|
|
||||||
|
private RichString beaconStationActiveText, beaconStationInactiveText;
|
||||||
|
|
||||||
/*private (Rectangle targetArea, string tip)? connectionTooltip;
|
/*private (Rectangle targetArea, string tip)? connectionTooltip;
|
||||||
private string sanitizedConnectionTooltip;
|
private string sanitizedConnectionTooltip;
|
||||||
private List<RichTextData> connectionTooltipRichTextData;
|
private List<RichTextData> connectionTooltipRichTextData;
|
||||||
@@ -153,6 +155,9 @@ namespace Barotrauma
|
|||||||
DebugConsole.ThrowError($"Could not find campaign map sprites for the biome \"{missingBiome.Identifier}\". Using the sprites of the first biome instead...");
|
DebugConsole.ThrowError($"Could not find campaign map sprites for the biome \"{missingBiome.Identifier}\". Using the sprites of the first biome instead...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beaconStationActiveText = RichString.Rich(TextManager.Get("BeaconStationActiveTooltip"));
|
||||||
|
beaconStationInactiveText = RichString.Rich(TextManager.Get("BeaconStationInactiveTooltip"));
|
||||||
|
|
||||||
RemoveFogOfWar(StartLocation);
|
RemoveFogOfWar(StartLocation);
|
||||||
|
|
||||||
GenerateLocationConnectionVisuals();
|
GenerateLocationConnectionVisuals();
|
||||||
@@ -619,7 +624,7 @@ namespace Barotrauma
|
|||||||
if (Vector2.Distance(PlayerInput.MousePosition, typeChangeIconPos) < generationParams.TypeChangeIcon.SourceRect.Width * zoom &&
|
if (Vector2.Distance(PlayerInput.MousePosition, typeChangeIconPos) < generationParams.TypeChangeIcon.SourceRect.Width * zoom &&
|
||||||
(tooltip == null || IsPreferredTooltip(typeChangeIconPos)))
|
(tooltip == null || IsPreferredTooltip(typeChangeIconPos)))
|
||||||
{
|
{
|
||||||
tooltip = (new Rectangle(typeChangeIconPos.ToPoint(), new Point(30)), location.LastTypeChangeMessage);
|
tooltip = (new Rectangle(typeChangeIconPos.ToPoint(), new Point(30)), RichString.Rich(location.LastTypeChangeMessage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (location != CurrentLocation && generationParams.MissionIcon != null)
|
if (location != CurrentLocation && generationParams.MissionIcon != null)
|
||||||
@@ -920,7 +925,7 @@ namespace Barotrauma
|
|||||||
if (connection.LevelData.HasBeaconStation)
|
if (connection.LevelData.HasBeaconStation)
|
||||||
{
|
{
|
||||||
var beaconStationIconStyle = connection.LevelData.IsBeaconActive ? "BeaconStationActive" : "BeaconStationInactive";
|
var beaconStationIconStyle = connection.LevelData.IsBeaconActive ? "BeaconStationActive" : "BeaconStationInactive";
|
||||||
DrawIcon(beaconStationIconStyle, (int)(28 * zoom), TextManager.Get(connection.LevelData.IsBeaconActive ? "BeaconStationActiveTooltip" : "BeaconStationInactiveTooltip"));
|
DrawIcon(beaconStationIconStyle, (int)(28 * zoom), connection.LevelData.IsBeaconActive ? beaconStationActiveText : beaconStationInactiveText);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connection.Locked)
|
if (connection.Locked)
|
||||||
@@ -942,9 +947,9 @@ namespace Barotrauma
|
|||||||
|
|
||||||
DrawIcon(
|
DrawIcon(
|
||||||
"LockedLocationConnection", (int)(28 * zoom),
|
"LockedLocationConnection", (int)(28 * zoom),
|
||||||
TextManager.GetWithVariables(unlockEvent.UnlockPathTooltip ?? "LockedPathTooltip",
|
RichString.Rich(TextManager.GetWithVariables(unlockEvent.UnlockPathTooltip ?? "LockedPathTooltip",
|
||||||
("[requiredreputation]", Reputation.GetFormattedReputationText(MathUtils.InverseLerp(unlockReputation.MinReputation, unlockReputation.MaxReputation, unlockEvent.UnlockPathReputation), unlockEvent.UnlockPathReputation, addColorTags: true)),
|
("[requiredreputation]", Reputation.GetFormattedReputationText(MathUtils.InverseLerp(unlockReputation.MinReputation, unlockReputation.MaxReputation, unlockEvent.UnlockPathReputation), unlockEvent.UnlockPathReputation, addColorTags: true)),
|
||||||
("[currentreputation]", unlockReputation.GetFormattedReputationText(addColorTags: true))));
|
("[currentreputation]", unlockReputation.GetFormattedReputationText(addColorTags: true)))));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -955,7 +960,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (connection.LevelData.HasHuntingGrounds)
|
if (connection.LevelData.HasHuntingGrounds)
|
||||||
{
|
{
|
||||||
DrawIcon("HuntingGrounds", (int)(28 * zoom), TextManager.Get("HuntingGroundsTooltip"));
|
DrawIcon("HuntingGrounds", (int)(28 * zoom), RichString.Rich(TextManager.Get("HuntingGroundsTooltip")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crushDepthWarningIconStyle != null)
|
if (crushDepthWarningIconStyle != null)
|
||||||
@@ -976,7 +981,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawIcon(string iconStyle, int iconSize, LocalizedString tooltipText)
|
void DrawIcon(string iconStyle, int iconSize, RichString tooltipText)
|
||||||
{
|
{
|
||||||
Vector2 iconPos = (connectionStart.Value + connectionEnd.Value) / 2;
|
Vector2 iconPos = (connectionStart.Value + connectionEnd.Value) / 2;
|
||||||
Vector2 iconDiff = Vector2.Normalize(connectionEnd.Value - connectionStart.Value) * iconSize;
|
Vector2 iconDiff = Vector2.Normalize(connectionEnd.Value - connectionStart.Value) * iconSize;
|
||||||
|
|||||||
@@ -526,22 +526,17 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
byte sectionCount = msg.ReadByte();
|
byte sectionCount = msg.ReadByte();
|
||||||
|
|
||||||
bool invalidMessage = false;
|
bool invalidMessage = false;
|
||||||
if (type != ServerNetObject.ENTITY_EVENT && type != ServerNetObject.ENTITY_EVENT_INITIAL)
|
if (sectionCount != Sections.Length)
|
||||||
{
|
|
||||||
DebugConsole.NewMessage($"Error while reading a network event for the structure \"{Name} ({ID})\". Invalid event type ({type}).", Color.Red);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (sectionCount != Sections.Length)
|
|
||||||
{
|
{
|
||||||
invalidMessage = true;
|
invalidMessage = true;
|
||||||
string errorMsg = $"Error while reading a network event for the structure \"{Name} ({ID})\". Section count does not match (server: {sectionCount} client: {Sections.Length})";
|
string errorMsg = $"Error while reading a network event for the structure \"{Name} ({ID})\". Section count does not match (server: {sectionCount} client: {Sections.Length})";
|
||||||
DebugConsole.NewMessage(errorMsg, Color.Red);
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce("Structure.ClientRead:SectionCountMismatch", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.AddErrorEventOnce("Structure.ClientRead:SectionCountMismatch", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
|
throw new Exception(errorMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < sectionCount; i++)
|
for (int i = 0; i < sectionCount; i++)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ using Barotrauma.Items.Components;
|
|||||||
|
|
||||||
namespace Barotrauma
|
namespace Barotrauma
|
||||||
{
|
{
|
||||||
partial class Submarine : Entity, IServerSerializable
|
partial class Submarine : Entity, IServerPositionSync
|
||||||
{
|
{
|
||||||
public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub)
|
public static Vector2 MouseToWorldGrid(Camera cam, Submarine sub)
|
||||||
{
|
{
|
||||||
@@ -547,19 +547,50 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int disabledItemLightCount = 0;
|
float entityCountWarningThreshold = 0.75f;
|
||||||
foreach (Item item in Item.ItemList)
|
|
||||||
|
if (Item.ItemList.Count > SubEditorScreen.MaxItems * entityCountWarningThreshold)
|
||||||
{
|
{
|
||||||
if (item.ParentInventory == null) { continue; }
|
if (!IsWarningSuppressed(SubEditorScreen.WarningType.ItemCount))
|
||||||
disabledItemLightCount += item.GetComponents<Items.Components.LightComponent>().Count();
|
{
|
||||||
|
errorMsgs.Add(TextManager.Get("subeditor.itemcountwarning").Value);
|
||||||
|
warnings.Add(SubEditorScreen.WarningType.ItemCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int count = GameMain.LightManager.Lights.Count(l => l.CastShadows) - disabledItemLightCount;
|
|
||||||
if (count > 45)
|
if ((MapEntity.mapEntityList.Count - Item.ItemList.Count - Hull.HullList.Count - WayPoint.WayPointList.Count - Gap.GapList.Count) > SubEditorScreen.MaxStructures * entityCountWarningThreshold)
|
||||||
{
|
{
|
||||||
if (!IsWarningSuppressed(SubEditorScreen.WarningType.TooManyLights))
|
if (!IsWarningSuppressed(SubEditorScreen.WarningType.StructureCount))
|
||||||
|
{
|
||||||
|
errorMsgs.Add(TextManager.Get("subeditor.structurecountwarning").Value);
|
||||||
|
warnings.Add(SubEditorScreen.WarningType.StructureCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Structure.WallList.Count > SubEditorScreen.MaxStructures * entityCountWarningThreshold)
|
||||||
|
{
|
||||||
|
if (!IsWarningSuppressed(SubEditorScreen.WarningType.WallCount))
|
||||||
|
{
|
||||||
|
errorMsgs.Add(TextManager.Get("subeditor.wallcountwarning").Value);
|
||||||
|
warnings.Add(SubEditorScreen.WarningType.WallCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetLightCount() > SubEditorScreen.MaxLights * entityCountWarningThreshold)
|
||||||
|
{
|
||||||
|
if (!IsWarningSuppressed(SubEditorScreen.WarningType.LightCount))
|
||||||
|
{
|
||||||
|
errorMsgs.Add(TextManager.Get("subeditor.lightcountwarning").Value);
|
||||||
|
warnings.Add(SubEditorScreen.WarningType.LightCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetShadowCastingLightCount() > SubEditorScreen.MaxShadowCastingLights * entityCountWarningThreshold)
|
||||||
|
{
|
||||||
|
if (!IsWarningSuppressed(SubEditorScreen.WarningType.ShadowCastingLightCount))
|
||||||
{
|
{
|
||||||
errorMsgs.Add(TextManager.Get("subeditor.shadowcastinglightswarning").Value);
|
errorMsgs.Add(TextManager.Get("subeditor.shadowcastinglightswarning").Value);
|
||||||
warnings.Add(SubEditorScreen.WarningType.TooManyLights);
|
warnings.Add(SubEditorScreen.WarningType.ShadowCastingLightCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,14 +658,31 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public static int GetLightCount()
|
||||||
{
|
{
|
||||||
if (type != ServerNetObject.ENTITY_POSITION)
|
int disabledItemLightCount = 0;
|
||||||
|
foreach (Item item in Item.ItemList)
|
||||||
{
|
{
|
||||||
DebugConsole.NewMessage($"Error while reading a network event for the submarine \"{Info.Name} ({ID})\". Invalid event type ({type}).", Color.Red);
|
if (item.ParentInventory == null) { continue; }
|
||||||
|
disabledItemLightCount += item.GetComponents<Items.Components.LightComponent>().Count();
|
||||||
}
|
}
|
||||||
|
return GameMain.LightManager.Lights.Count() - disabledItemLightCount;
|
||||||
|
}
|
||||||
|
|
||||||
var posInfo = PhysicsBody.ClientRead(type, msg, sendingTime, parentDebugName: Info.Name);
|
public static int GetShadowCastingLightCount()
|
||||||
|
{
|
||||||
|
int disabledItemLightCount = 0;
|
||||||
|
foreach (Item item in Item.ItemList)
|
||||||
|
{
|
||||||
|
if (item.ParentInventory == null) { continue; }
|
||||||
|
disabledItemLightCount += item.GetComponents<Items.Components.LightComponent>().Count();
|
||||||
|
}
|
||||||
|
return GameMain.LightManager.Lights.Count(l => l.CastShadows) - disabledItemLightCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClientReadPosition(IReadMessage msg, float sendingTime)
|
||||||
|
{
|
||||||
|
var posInfo = PhysicsBody.ClientRead(msg, sendingTime, parentDebugName: Info.Name);
|
||||||
msg.ReadPadBits();
|
msg.ReadPadBits();
|
||||||
|
|
||||||
if (posInfo != null)
|
if (posInfo != null)
|
||||||
@@ -648,5 +696,10 @@ namespace Barotrauma
|
|||||||
subBody.PositionBuffer.Insert(index, posInfo);
|
subBody.PositionBuffer.Insert(index, posInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
|
{
|
||||||
|
throw new Exception($"Error while reading a network event for the submarine \"{Info.Name} ({ID})\". Submarines are not even supposed to receive events!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
orderMessageInfo.TargetCharacter?.SetOrder(order);
|
orderMessageInfo.TargetCharacter?.SetOrder(order, orderMessageInfo.IsNewOrder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,7 +125,8 @@ namespace Barotrauma.Networking
|
|||||||
Order order = null;
|
Order order = null;
|
||||||
if (orderMessageInfo.TargetPosition != null)
|
if (orderMessageInfo.TargetPosition != null)
|
||||||
{
|
{
|
||||||
order = new Order(orderPrefab, orderOption, orderMessageInfo.Priority, Order.OrderType.Current, null, orderMessageInfo.TargetPosition, orderGiver: senderCharacter);
|
order = new Order(orderPrefab, orderOption, orderMessageInfo.TargetPosition, orderGiver: senderCharacter)
|
||||||
|
.WithManualPriority(orderMessageInfo.Priority);
|
||||||
}
|
}
|
||||||
else if (orderMessageInfo.WallSectionIndex != null)
|
else if (orderMessageInfo.WallSectionIndex != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO.Pipes;
|
using System.IO.Pipes;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Barotrauma.Networking
|
namespace Barotrauma.Networking
|
||||||
{
|
{
|
||||||
@@ -12,6 +13,9 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public static void Start(ProcessStartInfo processInfo)
|
public static void Start(ProcessStartInfo processInfo)
|
||||||
{
|
{
|
||||||
|
CrashString = null;
|
||||||
|
CrashReportFilePath = null;
|
||||||
|
|
||||||
writePipe = new AnonymousPipeServerStream(PipeDirection.Out, System.IO.HandleInheritability.Inheritable);
|
writePipe = new AnonymousPipeServerStream(PipeDirection.Out, System.IO.HandleInheritability.Inheritable);
|
||||||
readPipe = new AnonymousPipeServerStream(PipeDirection.In, System.IO.HandleInheritability.Inheritable);
|
readPipe = new AnonymousPipeServerStream(PipeDirection.In, System.IO.HandleInheritability.Inheritable);
|
||||||
|
|
||||||
@@ -42,8 +46,8 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
public static void ClosePipes()
|
public static void ClosePipes()
|
||||||
{
|
{
|
||||||
writePipe?.Close();
|
writePipe?.Dispose(); writePipe = null;
|
||||||
readPipe?.Close();
|
readPipe?.Dispose(); readPipe = null;
|
||||||
shutDown = true;
|
shutDown = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,5 +58,20 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
PrivateShutDown();
|
PrivateShutDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string CrashString { get; private set; }
|
||||||
|
public static string CrashReportFilePath { get; private set; }
|
||||||
|
|
||||||
|
public static LocalizedString CrashMessage
|
||||||
|
=> string.IsNullOrEmpty(CrashReportFilePath)
|
||||||
|
? TextManager.Get("ServerProcessClosed")
|
||||||
|
: TextManager.GetWithVariable("ServerProcessCrashed", "[reportfilepath]", CrashReportFilePath);
|
||||||
|
|
||||||
|
static partial void HandleCrashString(string str)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"The server has crashed: {str}");
|
||||||
|
CrashReportFilePath = str.Split("||").FirstOrDefault() ?? "servercrashreport.log";
|
||||||
|
CrashString = str;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
partial class EntitySpawner : Entity, IServerSerializable
|
partial class EntitySpawner : Entity, IServerSerializable
|
||||||
{
|
{
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage message, float sendingTime)
|
public void ClientEventRead(IReadMessage message, float sendingTime)
|
||||||
{
|
{
|
||||||
bool remove = message.ReadBoolean();
|
bool remove = message.ReadBoolean();
|
||||||
|
|
||||||
|
|||||||
@@ -666,7 +666,7 @@ namespace Barotrauma.Networking
|
|||||||
if (ChildServerRelay.Process?.HasExited ?? true)
|
if (ChildServerRelay.Process?.HasExited ?? true)
|
||||||
{
|
{
|
||||||
Disconnect();
|
Disconnect();
|
||||||
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), TextManager.Get("ServerProcessClosed"));
|
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage);
|
||||||
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
|
msgBox.Buttons[0].OnClicked += ReturnToPreviousMenu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -937,6 +937,9 @@ namespace Barotrauma.Networking
|
|||||||
case ServerPacketHeader.MEDICAL:
|
case ServerPacketHeader.MEDICAL:
|
||||||
campaign?.MedicalClinic?.ClientRead(inc);
|
campaign?.MedicalClinic?.ClientRead(inc);
|
||||||
break;
|
break;
|
||||||
|
case ServerPacketHeader.MONEY:
|
||||||
|
campaign?.ClientReadMoney(inc);
|
||||||
|
break;
|
||||||
case ServerPacketHeader.READY_CHECK:
|
case ServerPacketHeader.READY_CHECK:
|
||||||
ReadyCheck.ClientRead(inc);
|
ReadyCheck.ClientRead(inc);
|
||||||
break;
|
break;
|
||||||
@@ -1203,7 +1206,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
if (disconnectReason == DisconnectReason.ServerCrashed && IsServerOwner)
|
if (disconnectReason == DisconnectReason.ServerCrashed && IsServerOwner)
|
||||||
{
|
{
|
||||||
msg = TextManager.Get("ServerProcessCrashed");
|
msg = TextManager.GetWithVariable("ServerProcessCrashed", "[reportfilepath]", ChildServerRelay.CrashReportFilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2240,10 +2243,11 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readonly List<IServerSerializable> debugEntityList = new List<IServerSerializable>();
|
||||||
private void ReadIngameUpdate(IReadMessage inc)
|
private void ReadIngameUpdate(IReadMessage inc)
|
||||||
{
|
{
|
||||||
List<IServerSerializable> entities = new List<IServerSerializable>();
|
debugEntityList.Clear();
|
||||||
|
|
||||||
float sendingTime = inc.ReadSingle() - 0.0f;//TODO: reimplement inc.SenderConnection.RemoteTimeOffset;
|
float sendingTime = inc.ReadSingle() - 0.0f;//TODO: reimplement inc.SenderConnection.RemoteTimeOffset;
|
||||||
|
|
||||||
ServerNetObject? prevObjHeader = null;
|
ServerNetObject? prevObjHeader = null;
|
||||||
@@ -2284,15 +2288,15 @@ namespace Barotrauma.Networking
|
|||||||
uint msgLength = inc.ReadVariableUInt32();
|
uint msgLength = inc.ReadVariableUInt32();
|
||||||
int msgEndPos = (int)(inc.BitPosition + msgLength * 8);
|
int msgEndPos = (int)(inc.BitPosition + msgLength * 8);
|
||||||
|
|
||||||
var entity = Entity.FindEntityByID(id) as IServerSerializable;
|
var entity = Entity.FindEntityByID(id) as IServerPositionSync;
|
||||||
if (msgEndPos > inc.LengthBits)
|
if (msgEndPos > inc.LengthBits)
|
||||||
{
|
{
|
||||||
DebugConsole.ThrowError($"Error while reading a position update for the entity \"({entity?.ToString() ?? "null"})\". Message length exceeds the size of the buffer.");
|
DebugConsole.ThrowError($"Error while reading a position update for the entity \"({entity?.ToString() ?? "null"})\". Message length exceeds the size of the buffer.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
entities.Add(entity);
|
debugEntityList.Add(entity);
|
||||||
if (entity != null && (entity is Item || entity is Character || entity is Submarine))
|
if (entity != null)
|
||||||
{
|
{
|
||||||
if (entity is Item != isItem)
|
if (entity is Item != isItem)
|
||||||
{
|
{
|
||||||
@@ -2307,7 +2311,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
entity.ClientRead(objHeader.Value, inc, sendingTime);
|
entity.ClientReadPosition(inc, sendingTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2321,7 +2325,7 @@ namespace Barotrauma.Networking
|
|||||||
break;
|
break;
|
||||||
case ServerNetObject.ENTITY_EVENT:
|
case ServerNetObject.ENTITY_EVENT:
|
||||||
case ServerNetObject.ENTITY_EVENT_INITIAL:
|
case ServerNetObject.ENTITY_EVENT_INITIAL:
|
||||||
if (!entityEventManager.Read(objHeader.Value, inc, sendingTime, entities))
|
if (!entityEventManager.Read(objHeader.Value, inc, sendingTime, debugEntityList))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2340,7 +2344,6 @@ namespace Barotrauma.Networking
|
|||||||
prevBytePos = inc.BytePosition;
|
prevBytePos = inc.BytePosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
List<string> errorLines = new List<string>
|
List<string> errorLines = new List<string>
|
||||||
@@ -2359,7 +2362,7 @@ namespace Barotrauma.Networking
|
|||||||
objHeader == ServerNetObject.ENTITY_EVENT || objHeader == ServerNetObject.ENTITY_EVENT_INITIAL ||
|
objHeader == ServerNetObject.ENTITY_EVENT || objHeader == ServerNetObject.ENTITY_EVENT_INITIAL ||
|
||||||
objHeader == ServerNetObject.ENTITY_POSITION || prevObjHeader == ServerNetObject.ENTITY_POSITION)
|
objHeader == ServerNetObject.ENTITY_POSITION || prevObjHeader == ServerNetObject.ENTITY_POSITION)
|
||||||
{
|
{
|
||||||
foreach (IServerSerializable ent in entities)
|
foreach (IServerSerializable ent in debugEntityList)
|
||||||
{
|
{
|
||||||
if (ent == null)
|
if (ent == null)
|
||||||
{
|
{
|
||||||
@@ -2480,7 +2483,7 @@ namespace Barotrauma.Networking
|
|||||||
outmsg.Write(GameMain.NetLobbyScreen.CampaignCharacterDiscarded);
|
outmsg.Write(GameMain.NetLobbyScreen.CampaignCharacterDiscarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
Character.Controlled?.ClientWrite(outmsg);
|
Character.Controlled?.ClientWriteInput(outmsg);
|
||||||
GameMain.GameScreen.Cam?.ClientWrite(outmsg);
|
GameMain.GameScreen.Cam?.ClientWrite(outmsg);
|
||||||
|
|
||||||
entityEventManager.Write(outmsg, clientPeer?.ServerConnection);
|
entityEventManager.Write(outmsg, clientPeer?.ServerConnection);
|
||||||
@@ -2711,7 +2714,7 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CreateEntityEvent(INetSerializable entity, object[] extraData)
|
public override void CreateEntityEvent(INetSerializable entity, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
if (!(entity is IClientSerializable clientSerializable))
|
if (!(entity is IClientSerializable clientSerializable))
|
||||||
{
|
{
|
||||||
@@ -2770,7 +2773,7 @@ namespace Barotrauma.Networking
|
|||||||
if (ChildServerRelay.Process != null)
|
if (ChildServerRelay.Process != null)
|
||||||
{
|
{
|
||||||
int checks = 0;
|
int checks = 0;
|
||||||
while (ChildServerRelay.Process != null && !ChildServerRelay.Process.HasExited)
|
while (ChildServerRelay.Process is { HasExited: false })
|
||||||
{
|
{
|
||||||
if (checks > 10)
|
if (checks > 10)
|
||||||
{
|
{
|
||||||
|
|||||||
+13
-13
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
namespace Barotrauma.Networking
|
namespace Barotrauma.Networking
|
||||||
{
|
{
|
||||||
@@ -41,16 +42,16 @@ namespace Barotrauma.Networking
|
|||||||
thisClient = client;
|
thisClient = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CreateEvent(IClientSerializable entity, object[] extraData = null)
|
public void CreateEvent(IClientSerializable entity, NetEntityEvent.IData extraData = null)
|
||||||
{
|
{
|
||||||
if (GameMain.Client?.Character == null) { return; }
|
if (GameMain.Client?.Character == null) { return; }
|
||||||
|
|
||||||
if (!ValidateEntity(entity)) { return; }
|
if (!ValidateEntity(entity)) { return; }
|
||||||
|
|
||||||
var newEvent = new ClientEntityEvent(entity, (UInt16)(ID + 1))
|
var newEvent = new ClientEntityEvent(
|
||||||
{
|
entity,
|
||||||
CharacterStateID = GameMain.Client.Character.LastNetworkUpdateID
|
eventId: (UInt16)(ID + 1),
|
||||||
};
|
characterStateId: GameMain.Client.Character.LastNetworkUpdateID);
|
||||||
if (extraData != null) { newEvent.SetData(extraData); }
|
if (extraData != null) { newEvent.SetData(extraData); }
|
||||||
|
|
||||||
for (int i = events.Count - 1; i >= 0; i--)
|
for (int i = events.Count - 1; i >= 0; i--)
|
||||||
@@ -144,6 +145,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
entities.Clear();
|
entities.Clear();
|
||||||
|
|
||||||
|
msg.ReadPadBits();
|
||||||
UInt16 firstEventID = msg.ReadUInt16();
|
UInt16 firstEventID = msg.ReadUInt16();
|
||||||
int eventCount = msg.ReadByte();
|
int eventCount = msg.ReadByte();
|
||||||
|
|
||||||
@@ -172,7 +174,6 @@ namespace Barotrauma.Networking
|
|||||||
DebugConsole.NewMessage("received msg " + thisEventID + " (null entity)",
|
DebugConsole.NewMessage("received msg " + thisEventID + " (null entity)",
|
||||||
Microsoft.Xna.Framework.Color.Orange);
|
Microsoft.Xna.Framework.Color.Orange);
|
||||||
}
|
}
|
||||||
msg.ReadPadBits();
|
|
||||||
entities.Add(null);
|
entities.Add(null);
|
||||||
if (thisEventID == (UInt16)(lastReceivedID + 1)) { lastReceivedID++; }
|
if (thisEventID == (UInt16)(lastReceivedID + 1)) { lastReceivedID++; }
|
||||||
continue;
|
continue;
|
||||||
@@ -207,7 +208,6 @@ namespace Barotrauma.Networking
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg.BitPosition += msgLength * 8;
|
msg.BitPosition += msgLength * 8;
|
||||||
msg.ReadPadBits();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -239,22 +239,22 @@ namespace Barotrauma.Networking
|
|||||||
//msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
//msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
string errorMsg = "Failed to read event for entity \"" + entity.ToString() + "\" (" + e.Message + ")! (MidRoundSyncing: " + thisClient.MidRoundSyncing + ")\n" + e.StackTrace.CleanupStackTrace();
|
string errorMsg = $"Failed to read event {thisEventID} for entity \"{entity}\"" +
|
||||||
|
$"{(entity is Entity { ID: var entityId } ? $", id {entityId}" : "")} ";
|
||||||
|
DebugConsole.ThrowError(errorMsg, e);
|
||||||
|
|
||||||
|
errorMsg += $"({e.Message})! (MidRoundSyncing: {thisClient.MidRoundSyncing})\n{e.StackTrace.CleanupStackTrace()}";
|
||||||
errorMsg += "\nPrevious entities:";
|
errorMsg += "\nPrevious entities:";
|
||||||
for (int j = entities.Count - 2; j >= 0; j--)
|
for (int j = entities.Count - 2; j >= 0; j--)
|
||||||
{
|
{
|
||||||
errorMsg += "\n" + (entities[j] == null ? "NULL" : entities[j].ToString());
|
errorMsg += "\n" + (entities[j] == null ? "NULL" : entities[j].ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
|
|
||||||
|
|
||||||
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
||||||
GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||||
msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
||||||
msg.ReadPadBits();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,7 +272,7 @@ namespace Barotrauma.Networking
|
|||||||
|
|
||||||
protected void ReadEvent(IReadMessage buffer, IServerSerializable entity, float sendingTime)
|
protected void ReadEvent(IReadMessage buffer, IServerSerializable entity, float sendingTime)
|
||||||
{
|
{
|
||||||
entity.ClientRead(ServerNetObject.ENTITY_EVENT, buffer, sendingTime);
|
entity.ClientEventRead(buffer, sendingTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
|
|||||||
+6
-5
@@ -4,20 +4,21 @@ namespace Barotrauma.Networking
|
|||||||
{
|
{
|
||||||
class ClientEntityEvent : NetEntityEvent
|
class ClientEntityEvent : NetEntityEvent
|
||||||
{
|
{
|
||||||
private IClientSerializable serializable;
|
private readonly IClientSerializable serializable;
|
||||||
|
|
||||||
public UInt16 CharacterStateID;
|
public readonly UInt16 CharacterStateID;
|
||||||
|
|
||||||
public ClientEntityEvent(IClientSerializable entity, UInt16 id)
|
public ClientEntityEvent(IClientSerializable entity, UInt16 eventId, UInt16 characterStateId)
|
||||||
: base(entity, id)
|
: base(entity, eventId)
|
||||||
{
|
{
|
||||||
serializable = entity;
|
serializable = entity;
|
||||||
|
CharacterStateID = characterStateId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(IWriteMessage msg)
|
public void Write(IWriteMessage msg)
|
||||||
{
|
{
|
||||||
msg.Write(CharacterStateID);
|
msg.Write(CharacterStateID);
|
||||||
serializable.ClientWrite(msg, Data);
|
serializable.ClientEventWrite(msg, Data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -84,7 +84,7 @@ namespace Barotrauma.Networking
|
|||||||
if (ownerKey != 0 && (ChildServerRelay.Process?.HasExited ?? true))
|
if (ownerKey != 0 && (ChildServerRelay.Process?.HasExited ?? true))
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), TextManager.Get("ServerProcessClosed"));
|
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage);
|
||||||
msgBox.Buttons[0].OnClicked += (btn, obj) => { GameMain.MainMenuScreen.Select(); return false; };
|
msgBox.Buttons[0].OnClicked += (btn, obj) => { GameMain.MainMenuScreen.Select(); return false; };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -193,7 +193,7 @@ namespace Barotrauma.Networking
|
|||||||
if (ChildServerRelay.HasShutDown || (ChildServerRelay.Process?.HasExited ?? true))
|
if (ChildServerRelay.HasShutDown || (ChildServerRelay.Process?.HasExited ?? true))
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), TextManager.Get("ServerProcessClosed"));
|
var msgBox = new GUIMessageBox(TextManager.Get("ConnectionLost"), ChildServerRelay.CrashMessage);
|
||||||
msgBox.Buttons[0].OnClicked += (btn, obj) => { GameMain.MainMenuScreen.Select(); return false; };
|
msgBox.Buttons[0].OnClicked += (btn, obj) => { GameMain.MainMenuScreen.Select(); return false; };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ namespace Barotrauma.Networking
|
|||||||
}, delay: delay);
|
}, delay: delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
|
public void ClientEventRead(IReadMessage msg, float sendingTime)
|
||||||
{
|
{
|
||||||
bool respawnPromptPending = false;
|
bool respawnPromptPending = false;
|
||||||
var newState = (State)msg.ReadRangedInteger(0, Enum.GetNames(typeof(State)).Length);
|
var newState = (State)msg.ReadRangedInteger(0, Enum.GetNames(typeof(State)).Length);
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PosInfo ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime, string parentDebugName)
|
public PosInfo ClientRead(IReadMessage msg, float sendingTime, string parentDebugName)
|
||||||
{
|
{
|
||||||
float MaxVel = NetConfig.MaxPhysicsBodyVelocity;
|
float MaxVel = NetConfig.MaxPhysicsBodyVelocity;
|
||||||
float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;
|
float MaxAngularVel = NetConfig.MaxPhysicsBodyAngularVelocity;
|
||||||
|
|||||||
+11
@@ -278,6 +278,17 @@ namespace Barotrauma
|
|||||||
characterInfos.Add((new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: jobPrefab, variant: variant), jobPrefab));
|
characterInfos.Add((new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: jobPrefab, variant: variant), jobPrefab));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (characterInfos.Count == 0)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"No starting crew found! If you're using mods, it may be that the mods have overridden the vanilla jobs without specifying which types of characters the starting crew should consist of. If you're the developer of the mod, ensure that you've set the {nameof(JobPrefab.InitialCount)} properties for the custom jobs.");
|
||||||
|
DebugConsole.AddWarning("Choosing the first available jobs as the starting crew...");
|
||||||
|
foreach (JobPrefab jobPrefab in JobPrefab.Prefabs)
|
||||||
|
{
|
||||||
|
var variant = Rand.Range(0, jobPrefab.Variants);
|
||||||
|
characterInfos.Add((new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: jobPrefab, variant: variant), jobPrefab));
|
||||||
|
if (characterInfos.Count >= 3) { break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
characterInfos.Sort((a, b) => Math.Sign(b.Job.MinKarma - a.Job.MinKarma));
|
characterInfos.Sort((a, b) => Math.Sign(b.Job.MinKarma - a.Job.MinKarma));
|
||||||
|
|
||||||
characterInfoColumns.ClearChildren();
|
characterInfoColumns.ClearChildren();
|
||||||
|
|||||||
@@ -143,14 +143,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (Campaign.PurchasedHullRepairs)
|
if (Campaign.PurchasedHullRepairs)
|
||||||
{
|
{
|
||||||
Campaign.Money += CampaignMode.HullRepairCost;
|
Campaign.Wallet.Refund(CampaignMode.HullRepairCost);
|
||||||
Campaign.PurchasedHullRepairs = false;
|
Campaign.PurchasedHullRepairs = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Campaign.Money >= CampaignMode.HullRepairCost)
|
if (Campaign.Wallet.TryDeduct(CampaignMode.HullRepairCost))
|
||||||
{
|
{
|
||||||
Campaign.Money -= CampaignMode.HullRepairCost;
|
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.HullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
|
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.HullRepairCost, GameAnalyticsManager.MoneySink.Service, "hullrepairs");
|
||||||
Campaign.PurchasedHullRepairs = true;
|
Campaign.PurchasedHullRepairs = true;
|
||||||
}
|
}
|
||||||
@@ -189,14 +188,13 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
if (Campaign.PurchasedItemRepairs)
|
if (Campaign.PurchasedItemRepairs)
|
||||||
{
|
{
|
||||||
Campaign.Money += CampaignMode.ItemRepairCost;
|
Campaign.Wallet.Refund(CampaignMode.ItemRepairCost);
|
||||||
Campaign.PurchasedItemRepairs = false;
|
Campaign.PurchasedItemRepairs = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Campaign.Money >= CampaignMode.ItemRepairCost)
|
if (Campaign.Wallet.TryDeduct(CampaignMode.ItemRepairCost))
|
||||||
{
|
{
|
||||||
Campaign.Money -= CampaignMode.ItemRepairCost;
|
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.ItemRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
|
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.ItemRepairCost, GameAnalyticsManager.MoneySink.Service, "devicerepairs");
|
||||||
Campaign.PurchasedItemRepairs = true;
|
Campaign.PurchasedItemRepairs = true;
|
||||||
}
|
}
|
||||||
@@ -242,14 +240,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
if (Campaign.PurchasedLostShuttles)
|
if (Campaign.PurchasedLostShuttles)
|
||||||
{
|
{
|
||||||
Campaign.Money += CampaignMode.ShuttleReplaceCost;
|
Campaign.Wallet.Refund(CampaignMode.ShuttleReplaceCost);
|
||||||
Campaign.PurchasedLostShuttles = false;
|
Campaign.PurchasedLostShuttles = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Campaign.Money >= CampaignMode.ShuttleReplaceCost)
|
if (Campaign.Wallet.TryDeduct(CampaignMode.ShuttleReplaceCost))
|
||||||
{
|
{
|
||||||
Campaign.Money -= CampaignMode.ShuttleReplaceCost;
|
|
||||||
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.ShuttleReplaceCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
|
GameAnalyticsManager.AddMoneySpentEvent(CampaignMode.ShuttleReplaceCost, GameAnalyticsManager.MoneySink.Service, "retrieveshuttle");
|
||||||
Campaign.PurchasedLostShuttles = true;
|
Campaign.PurchasedLostShuttles = true;
|
||||||
}
|
}
|
||||||
@@ -445,7 +442,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Color = MapGenerationParams.Instance.IndicatorColor,
|
Color = MapGenerationParams.Instance.IndicatorColor,
|
||||||
HoverColor = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f),
|
HoverColor = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f),
|
||||||
ToolTip = TextManager.Get(connection.LevelData.IsBeaconActive ? "BeaconStationActiveTooltip" : "BeaconStationInactiveTooltip")
|
ToolTip = RichString.Rich(TextManager.Get(connection.LevelData.IsBeaconActive ? "BeaconStationActiveTooltip" : "BeaconStationInactiveTooltip"))
|
||||||
};
|
};
|
||||||
new GUITextBlock(new RectTransform(Vector2.One, beaconStationContent.RectTransform),
|
new GUITextBlock(new RectTransform(Vector2.One, beaconStationContent.RectTransform),
|
||||||
TextManager.Get("submarinetype.beaconstation", "beaconstationsonarlabel"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
TextManager.Get("submarinetype.beaconstation", "beaconstationsonarlabel"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
||||||
@@ -462,7 +459,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
Color = MapGenerationParams.Instance.IndicatorColor,
|
Color = MapGenerationParams.Instance.IndicatorColor,
|
||||||
HoverColor = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f),
|
HoverColor = Color.Lerp(MapGenerationParams.Instance.IndicatorColor, Color.White, 0.5f),
|
||||||
ToolTip = TextManager.Get("HuntingGroundsTooltip")
|
ToolTip = RichString.Rich(TextManager.Get("HuntingGroundsTooltip"))
|
||||||
};
|
};
|
||||||
new GUITextBlock(new RectTransform(Vector2.One, huntingGroundsContent.RectTransform),
|
new GUITextBlock(new RectTransform(Vector2.One, huntingGroundsContent.RectTransform),
|
||||||
TextManager.Get("missionname.huntinggrounds"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
TextManager.Get("missionname.huntinggrounds"), font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
||||||
@@ -705,11 +702,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
case CampaignMode.InteractionType.Repair:
|
case CampaignMode.InteractionType.Repair:
|
||||||
repairHullsButton.Enabled =
|
repairHullsButton.Enabled =
|
||||||
(Campaign.PurchasedHullRepairs || Campaign.Money >= CampaignMode.HullRepairCost) &&
|
(Campaign.PurchasedHullRepairs || Campaign.Wallet.CanAfford(CampaignMode.HullRepairCost)) &&
|
||||||
Campaign.AllowedToManageCampaign();
|
Campaign.AllowedToManageCampaign();
|
||||||
repairHullsButton.GetChild<GUITickBox>().Selected = Campaign.PurchasedHullRepairs;
|
repairHullsButton.GetChild<GUITickBox>().Selected = Campaign.PurchasedHullRepairs;
|
||||||
repairItemsButton.Enabled =
|
repairItemsButton.Enabled =
|
||||||
(Campaign.PurchasedItemRepairs || Campaign.Money >= CampaignMode.ItemRepairCost) &&
|
(Campaign.PurchasedItemRepairs || Campaign.Wallet.CanAfford(CampaignMode.ItemRepairCost)) &&
|
||||||
Campaign.AllowedToManageCampaign();
|
Campaign.AllowedToManageCampaign();
|
||||||
repairItemsButton.GetChild<GUITickBox>().Selected = Campaign.PurchasedItemRepairs;
|
repairItemsButton.GetChild<GUITickBox>().Selected = Campaign.PurchasedItemRepairs;
|
||||||
|
|
||||||
@@ -721,7 +718,7 @@ namespace Barotrauma
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
replaceShuttlesButton.Enabled =
|
replaceShuttlesButton.Enabled =
|
||||||
(Campaign.PurchasedLostShuttles || Campaign.Money >= CampaignMode.ShuttleReplaceCost) &&
|
(Campaign.PurchasedLostShuttles || Campaign.Wallet.CanAfford(CampaignMode.ShuttleReplaceCost)) &&
|
||||||
Campaign.AllowedToManageCampaign();
|
Campaign.AllowedToManageCampaign();
|
||||||
replaceShuttlesButton.GetChild<GUITickBox>().Selected = Campaign.PurchasedLostShuttles;
|
replaceShuttlesButton.GetChild<GUITickBox>().Selected = Campaign.PurchasedLostShuttles;
|
||||||
}
|
}
|
||||||
@@ -742,7 +739,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public static LocalizedString GetMoney()
|
public static LocalizedString GetMoney()
|
||||||
{
|
{
|
||||||
return TextManager.GetWithVariable("PlayerCredits", "[credits]", (GameMain.GameSession?.Campaign == null) ? "0" : string.Format(CultureInfo.InvariantCulture, "{0:N0}", GameMain.GameSession.Campaign.Money));
|
return TextManager.GetWithVariable("PlayerCredits", "[credits]", (GameMain.GameSession?.Campaign == null) ? "0" : string.Format(CultureInfo.InvariantCulture, "{0:N0}", GameMain.GameSession.Campaign.Wallet.Balance));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateMaxMissions(Location location)
|
private void UpdateMaxMissions(Location location)
|
||||||
|
|||||||
+4
-10
@@ -1668,11 +1668,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
|
|
||||||
if (contentPackage == null)
|
if (contentPackage == null)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
|
||||||
contentPackage = ContentPackageManager.EnabledPackages.All.LastOrDefault();
|
|
||||||
#else
|
|
||||||
contentPackage = ContentPackageManager.EnabledPackages.All.LastOrDefault(cp => cp != vanilla);
|
contentPackage = ContentPackageManager.EnabledPackages.All.LastOrDefault(cp => cp != vanilla);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (contentPackage == null)
|
if (contentPackage == null)
|
||||||
{
|
{
|
||||||
@@ -1680,13 +1676,11 @@ namespace Barotrauma.CharacterEditor
|
|||||||
DebugConsole.ThrowError(GetCharacterEditorTranslation("NoContentPackageSelected"));
|
DebugConsole.ThrowError(GetCharacterEditorTranslation("NoContentPackageSelected"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#if !DEBUG
|
|
||||||
if (vanilla != null && contentPackage == vanilla)
|
if (vanilla != null && contentPackage == vanilla)
|
||||||
{
|
{
|
||||||
GUI.AddMessage(GetCharacterEditorTranslation("CannotEditVanillaCharacters"), GUIStyle.Red, font: GUIStyle.LargeFont);
|
GUI.AddMessage(GetCharacterEditorTranslation("CannotEditVanillaCharacters"), GUIStyle.Red, font: GUIStyle.LargeFont);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
// Content package
|
// Content package
|
||||||
if (contentPackage is RegularPackage regular && !ContentPackageManager.EnabledPackages.Regular.Contains(regular))
|
if (contentPackage is RegularPackage regular && !ContentPackageManager.EnabledPackages.Regular.Contains(regular))
|
||||||
{
|
{
|
||||||
@@ -1721,9 +1715,9 @@ namespace Barotrauma.CharacterEditor
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
config.SetAttributeValue("speciesname", name);
|
config.SetAttributeValue("speciesname", name, StringComparison.OrdinalIgnoreCase);
|
||||||
config.SetAttributeValue("humanoid", isHumanoid);
|
config.SetAttributeValue("humanoid", isHumanoid, StringComparison.OrdinalIgnoreCase);
|
||||||
var ragdollElement = config.Element("ragdolls");
|
var ragdollElement = config.GetChildElement("ragdolls");
|
||||||
if (ragdollElement == null)
|
if (ragdollElement == null)
|
||||||
{
|
{
|
||||||
config.Add(new XElement("ragdolls", CreateRagdollPath()));
|
config.Add(new XElement("ragdolls", CreateRagdollPath()));
|
||||||
@@ -1736,7 +1730,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
ragdollElement.ReplaceWith(new XElement("ragdolls", CreateRagdollPath()));
|
ragdollElement.ReplaceWith(new XElement("ragdolls", CreateRagdollPath()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var animationElement = config.Element("animations");
|
var animationElement = config.GetChildElement("animations");
|
||||||
if (animationElement == null)
|
if (animationElement == null)
|
||||||
{
|
{
|
||||||
config.Add(new XElement("animations", CreateAnimationPath()));
|
config.Add(new XElement("animations", CreateAnimationPath()));
|
||||||
|
|||||||
@@ -160,8 +160,7 @@ namespace Barotrauma.CharacterEditor
|
|||||||
bool isTextureSelected = false;
|
bool isTextureSelected = false;
|
||||||
void UpdatePaths()
|
void UpdatePaths()
|
||||||
{
|
{
|
||||||
string pathBase = ContentPackage == GameMain.VanillaContent ? $"Content/Characters/{Name}/{Name}"
|
string pathBase = $"{ContentPath.ModDirStr}/Characters/{Name}/{Name}";
|
||||||
: $"{ContentPath.ModDirStr}/Characters/{Name}/{Name}";
|
|
||||||
XMLPath = $"{pathBase}.xml";
|
XMLPath = $"{pathBase}.xml";
|
||||||
xmlPathElement.Text = XMLPath;
|
xmlPathElement.Text = XMLPath;
|
||||||
if (updateTexturePath)
|
if (updateTexturePath)
|
||||||
@@ -307,10 +306,10 @@ namespace Barotrauma.CharacterEditor
|
|||||||
contentPackageDropDown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.5f), rightContainer.RectTransform, Anchor.TopRight));
|
contentPackageDropDown = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.5f), rightContainer.RectTransform, Anchor.TopRight));
|
||||||
foreach (ContentPackage contentPackage in ContentPackageManager.EnabledPackages.All)
|
foreach (ContentPackage contentPackage in ContentPackageManager.EnabledPackages.All)
|
||||||
{
|
{
|
||||||
#if !DEBUG
|
if (contentPackage != GameMain.VanillaContent)
|
||||||
if (contentPackage == GameMain.VanillaContent) { continue; }
|
{
|
||||||
#endif
|
contentPackageDropDown.AddItem(contentPackage.Name, userData: contentPackage, toolTip: contentPackage.Path);
|
||||||
contentPackageDropDown.AddItem(contentPackage.Name, userData: contentPackage, toolTip: contentPackage.Path);
|
}
|
||||||
}
|
}
|
||||||
contentPackageDropDown.OnSelected = (obj, userdata) =>
|
contentPackageDropDown.OnSelected = (obj, userdata) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1329,6 +1329,11 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
SeedBox.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
SeedBox.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
||||||
levelDifficultyScrollBar.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
levelDifficultyScrollBar.Enabled = !CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
||||||
|
levelDifficultyScrollBar.ToolTip = string.Empty;
|
||||||
|
if (!levelDifficultyScrollBar.Enabled)
|
||||||
|
{
|
||||||
|
levelDifficultyScrollBar.ToolTip = TextManager.Get("campaigndifficultydisabled");
|
||||||
|
}
|
||||||
|
|
||||||
traitorProbabilityButtons[0].Enabled = traitorProbabilityButtons[1].Enabled = traitorProbabilityText.Enabled =
|
traitorProbabilityButtons[0].Enabled = traitorProbabilityButtons[1].Enabled = traitorProbabilityText.Enabled =
|
||||||
!CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
!CampaignFrame.Visible && !CampaignSetupFrame.Visible && GameMain.Client.HasPermission(ClientPermissions.ManageSettings);
|
||||||
|
|||||||
@@ -32,7 +32,10 @@ namespace Barotrauma
|
|||||||
private GUIScrollBar zoomBar;
|
private GUIScrollBar zoomBar;
|
||||||
private readonly List<Sprite> selectedSprites = new List<Sprite>();
|
private readonly List<Sprite> selectedSprites = new List<Sprite>();
|
||||||
private readonly List<Sprite> dirtySprites = new List<Sprite>();
|
private readonly List<Sprite> dirtySprites = new List<Sprite>();
|
||||||
private Sprite selectedTexture;
|
private Texture2D SelectedTexture => lastSprite?.Texture;
|
||||||
|
private Sprite lastSprite;
|
||||||
|
private string selectedTexturePath;
|
||||||
|
|
||||||
private Rectangle textureRect;
|
private Rectangle textureRect;
|
||||||
private float zoom = 1;
|
private float zoom = 1;
|
||||||
private const float MinZoom = 0.25f, MaxZoom = 10.0f;
|
private const float MinZoom = 0.25f, MaxZoom = 10.0f;
|
||||||
@@ -82,12 +85,11 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
OnClicked = (button, userData) =>
|
OnClicked = (button, userData) =>
|
||||||
{
|
{
|
||||||
if (!(textureList.SelectedData is Texture2D selectedTexture)) { return false; }
|
|
||||||
var selected = selectedSprites;
|
var selected = selectedSprites;
|
||||||
Sprite firstSelected = selected.First();
|
Sprite firstSelected = selected.First();
|
||||||
selected.ForEach(s => s.ReloadTexture());
|
selected.ForEach(s => s.ReloadTexture());
|
||||||
RefreshLists();
|
RefreshLists();
|
||||||
textureList.Select(firstSelected.Texture, autoScroll: false);
|
textureList.Select(firstSelected.FullPath, autoScroll: false);
|
||||||
selected.ForEachMod(s => spriteList.Select(s, autoScroll: false));
|
selected.ForEachMod(s => spriteList.Select(s, autoScroll: false));
|
||||||
texturePathText.Text = TextManager.GetWithVariable("spriteeditor.texturesreloaded", "[filepath]", firstSelected.FilePath.Value);
|
texturePathText.Text = TextManager.GetWithVariable("spriteeditor.texturesreloaded", "[filepath]", firstSelected.FilePath.Value);
|
||||||
texturePathText.TextColor = GUIStyle.Green;
|
texturePathText.TextColor = GUIStyle.Green;
|
||||||
@@ -101,10 +103,10 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
OnClicked = (button, userData) =>
|
OnClicked = (button, userData) =>
|
||||||
{
|
{
|
||||||
if (selectedTexture == null) { return false; }
|
if (SelectedTexture == null) { return false; }
|
||||||
foreach (Sprite sprite in loadedSprites)
|
foreach (Sprite sprite in loadedSprites)
|
||||||
{
|
{
|
||||||
if (sprite.FullPath != selectedTexture.FullPath) { continue; }
|
if (sprite.FullPath != selectedTexturePath) { continue; }
|
||||||
var element = sprite.SourceElement;
|
var element = sprite.SourceElement;
|
||||||
if (element == null) { continue; }
|
if (element == null) { continue; }
|
||||||
// Not all sprites have a sourcerect defined, in which case we'll want to use the current source rect instead of an empty rect.
|
// Not all sprites have a sourcerect defined, in which case we'll want to use the current source rect instead of an empty rect.
|
||||||
@@ -206,23 +208,20 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
OnSelected = (listBox, userData) =>
|
OnSelected = (listBox, userData) =>
|
||||||
{
|
{
|
||||||
var previousSprite = selectedTexture;
|
var newTexturePath = userData as string;
|
||||||
selectedTexture = userData as Sprite;
|
if (selectedTexturePath == null || selectedTexturePath != newTexturePath)
|
||||||
if (previousSprite != selectedTexture)
|
|
||||||
{
|
{
|
||||||
|
selectedTexturePath = newTexturePath;
|
||||||
ResetZoom();
|
ResetZoom();
|
||||||
|
spriteList.Select(loadedSprites.First(s => s.FilePath == selectedTexturePath), autoScroll: false);
|
||||||
|
UpdateScrollBar(spriteList);
|
||||||
}
|
}
|
||||||
foreach (GUIComponent child in spriteList.Content.Children)
|
foreach (GUIComponent child in spriteList.Content.Children)
|
||||||
{
|
{
|
||||||
var textBlock = (GUITextBlock)child;
|
var textBlock = (GUITextBlock)child;
|
||||||
var sprite = (Sprite)textBlock.UserData;
|
var sprite = (Sprite)textBlock.UserData;
|
||||||
textBlock.TextColor = new Color(textBlock.TextColor, sprite.FilePath == selectedTexture.FilePath ? 1.0f : 0.4f);
|
textBlock.TextColor = new Color(textBlock.TextColor, sprite.FilePath == selectedTexturePath ? 1.0f : 0.4f);
|
||||||
if (sprite.FilePath == selectedTexture.FilePath) { textBlock.Visible = true; }
|
if (sprite.FilePath == selectedTexturePath) { textBlock.Visible = true; }
|
||||||
}
|
|
||||||
if (selectedSprites.None(s => s.FilePath == selectedTexture.FilePath))
|
|
||||||
{
|
|
||||||
spriteList.Select(loadedSprites.First(s => s.FilePath == selectedTexture.FilePath), autoScroll: false);
|
|
||||||
UpdateScrollBar(spriteList);
|
|
||||||
}
|
}
|
||||||
texturePathText.TextColor = Color.LightGray;
|
texturePathText.TextColor = Color.LightGray;
|
||||||
topPanelContents.Visible = true;
|
topPanelContents.Visible = true;
|
||||||
@@ -251,9 +250,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
OnSelected = (listBox, userData) =>
|
OnSelected = (listBox, userData) =>
|
||||||
{
|
{
|
||||||
if (!(userData is Sprite sprite)) return false;
|
if (userData is Sprite sprite)
|
||||||
SelectSprite(sprite);
|
{
|
||||||
return true;
|
SelectSprite(sprite);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -410,12 +412,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private bool SaveSprites(IEnumerable<Sprite> sprites)
|
private bool SaveSprites(IEnumerable<Sprite> sprites)
|
||||||
{
|
{
|
||||||
if (selectedTexture == null) { return false; }
|
if (SelectedTexture == null) { return false; }
|
||||||
if (sprites.None()) { return false; }
|
if (sprites.None()) { return false; }
|
||||||
HashSet<XDocument> docsToSave = new HashSet<XDocument>();
|
HashSet<XDocument> docsToSave = new HashSet<XDocument>();
|
||||||
foreach (Sprite sprite in sprites)
|
foreach (Sprite sprite in sprites)
|
||||||
{
|
{
|
||||||
if (sprite.FullPath != selectedTexture.FullPath) { continue; }
|
if (sprite.FullPath != selectedTexturePath) { continue; }
|
||||||
var element = sprite.SourceElement;
|
var element = sprite.SourceElement;
|
||||||
if (element == null) { continue; }
|
if (element == null) { continue; }
|
||||||
element.SetAttributeValue("sourcerect", XMLExtensions.RectToString(sprite.SourceRect));
|
element.SetAttributeValue("sourcerect", XMLExtensions.RectToString(sprite.SourceRect));
|
||||||
@@ -469,11 +471,11 @@ namespace Barotrauma
|
|||||||
// Select rects with the mouse
|
// Select rects with the mouse
|
||||||
if (Widget.selectedWidgets.None() || Widget.EnableMultiSelect)
|
if (Widget.selectedWidgets.None() || Widget.EnableMultiSelect)
|
||||||
{
|
{
|
||||||
if (selectedTexture != null && GUI.MouseOn == null)
|
if (SelectedTexture != null && GUI.MouseOn == null)
|
||||||
{
|
{
|
||||||
foreach (Sprite sprite in loadedSprites)
|
foreach (Sprite sprite in loadedSprites)
|
||||||
{
|
{
|
||||||
if (sprite.FullPath != selectedTexture.FullPath) { continue; }
|
if (sprite.FullPath != selectedTexturePath) { continue; }
|
||||||
if (PlayerInput.PrimaryMouseButtonClicked())
|
if (PlayerInput.PrimaryMouseButtonClicked())
|
||||||
{
|
{
|
||||||
var scaledRect = new Rectangle(textureRect.Location + sprite.SourceRect.Location.Multiply(zoom), sprite.SourceRect.Size.Multiply(zoom));
|
var scaledRect = new Rectangle(textureRect.Location + sprite.SourceRect.Location.Multiply(zoom), sprite.SourceRect.Size.Multiply(zoom));
|
||||||
@@ -637,20 +639,20 @@ namespace Barotrauma
|
|||||||
|
|
||||||
var viewArea = GetViewArea;
|
var viewArea = GetViewArea;
|
||||||
|
|
||||||
if (selectedTexture != null)
|
if (SelectedTexture != null)
|
||||||
{
|
{
|
||||||
textureRect = new Rectangle(
|
textureRect = new Rectangle(
|
||||||
(int)(viewArea.Center.X - selectedTexture.Texture.Bounds.Width / 2f * zoom),
|
(int)(viewArea.Center.X - SelectedTexture.Bounds.Width / 2f * zoom),
|
||||||
(int)(viewArea.Center.Y - selectedTexture.Texture.Bounds.Height / 2f * zoom),
|
(int)(viewArea.Center.Y - SelectedTexture.Bounds.Height / 2f * zoom),
|
||||||
(int)(selectedTexture.Texture.Bounds.Width * zoom),
|
(int)(SelectedTexture.Bounds.Width * zoom),
|
||||||
(int)(selectedTexture.Texture.Bounds.Height * zoom));
|
(int)(SelectedTexture.Bounds.Height * zoom));
|
||||||
|
|
||||||
spriteBatch.Draw(selectedTexture.Texture,
|
spriteBatch.Draw(SelectedTexture,
|
||||||
viewArea.Center.ToVector2(),
|
viewArea.Center.ToVector2(),
|
||||||
sourceRectangle: null,
|
sourceRectangle: null,
|
||||||
color: Color.White,
|
color: Color.White,
|
||||||
rotation: 0.0f,
|
rotation: 0.0f,
|
||||||
origin: new Vector2(selectedTexture.Texture.Bounds.Width / 2.0f, selectedTexture.Texture.Bounds.Height / 2.0f),
|
origin: new Vector2(SelectedTexture.Bounds.Width / 2.0f, SelectedTexture.Bounds.Height / 2.0f),
|
||||||
scale: zoom,
|
scale: zoom,
|
||||||
effects: SpriteEffects.None,
|
effects: SpriteEffects.None,
|
||||||
layerDepth: 0);
|
layerDepth: 0);
|
||||||
@@ -666,7 +668,7 @@ namespace Barotrauma
|
|||||||
foreach (GUIComponent element in spriteList.Content.Children)
|
foreach (GUIComponent element in spriteList.Content.Children)
|
||||||
{
|
{
|
||||||
if (!(element.UserData is Sprite sprite)) { continue; }
|
if (!(element.UserData is Sprite sprite)) { continue; }
|
||||||
if (sprite.FullPath != selectedTexture.FullPath) { continue; }
|
if (sprite.FullPath != selectedTexturePath) { continue; }
|
||||||
|
|
||||||
Rectangle sourceRect = new Rectangle(
|
Rectangle sourceRect = new Rectangle(
|
||||||
textureRect.X + (int)(sprite.SourceRect.X * zoom),
|
textureRect.X + (int)(sprite.SourceRect.X * zoom),
|
||||||
@@ -874,13 +876,13 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void SelectSprite(Sprite sprite)
|
public void SelectSprite(Sprite sprite)
|
||||||
{
|
{
|
||||||
|
lastSprite = sprite;
|
||||||
if (!loadedSprites.Contains(sprite))
|
if (!loadedSprites.Contains(sprite))
|
||||||
{
|
{
|
||||||
loadedSprites.Add(sprite);
|
loadedSprites.Add(sprite);
|
||||||
RefreshLists();
|
RefreshLists();
|
||||||
}
|
}
|
||||||
|
if (selectedSprites.Any(s => s.FullPath != selectedTexturePath))
|
||||||
if (selectedSprites.Any(s => s.FullPath != selectedTexture.FullPath))
|
|
||||||
{
|
{
|
||||||
ResetWidgets();
|
ResetWidgets();
|
||||||
}
|
}
|
||||||
@@ -902,9 +904,9 @@ namespace Barotrauma
|
|||||||
selectedSprites.Add(sprite);
|
selectedSprites.Add(sprite);
|
||||||
dirtySprites.Add(sprite);
|
dirtySprites.Add(sprite);
|
||||||
}
|
}
|
||||||
if (selectedTexture?.FullPath != sprite.FullPath)
|
if (sprite.FullPath != selectedTexturePath)
|
||||||
{
|
{
|
||||||
textureList.Select(sprite.Texture, autoScroll: false);
|
textureList.Select(sprite.FullPath, autoScroll: false);
|
||||||
UpdateScrollBar(textureList);
|
UpdateScrollBar(textureList);
|
||||||
}
|
}
|
||||||
xmlPathText.Text = string.Empty;
|
xmlPathText.Text = string.Empty;
|
||||||
@@ -926,7 +928,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void RefreshLists()
|
public void RefreshLists()
|
||||||
{
|
{
|
||||||
//selectedTexture = null;
|
|
||||||
selectedSprites.Clear();
|
selectedSprites.Clear();
|
||||||
textureList.ClearChildren();
|
textureList.ClearChildren();
|
||||||
spriteList.ClearChildren();
|
spriteList.ClearChildren();
|
||||||
@@ -936,7 +937,7 @@ namespace Barotrauma
|
|||||||
foreach (Sprite sprite in loadedSprites.OrderBy(s => Path.GetFileNameWithoutExtension(s.FilePath.Value)))
|
foreach (Sprite sprite in loadedSprites.OrderBy(s => Path.GetFileNameWithoutExtension(s.FilePath.Value)))
|
||||||
{
|
{
|
||||||
//ignore sprites that don't have a file path (e.g. submarine pics)
|
//ignore sprites that don't have a file path (e.g. submarine pics)
|
||||||
if (sprite.FilePath.IsNullOrEmpty()) continue;
|
if (sprite.FilePath.IsNullOrEmpty()) { continue; }
|
||||||
string normalizedFilePath = sprite.FilePath.FullPath;
|
string normalizedFilePath = sprite.FilePath.FullPath;
|
||||||
if (!textures.Contains(normalizedFilePath))
|
if (!textures.Contains(normalizedFilePath))
|
||||||
{
|
{
|
||||||
@@ -944,7 +945,7 @@ namespace Barotrauma
|
|||||||
Path.GetFileName(sprite.FilePath.Value))
|
Path.GetFileName(sprite.FilePath.Value))
|
||||||
{
|
{
|
||||||
ToolTip = sprite.FilePath.Value,
|
ToolTip = sprite.FilePath.Value,
|
||||||
UserData = sprite
|
UserData = sprite.FullPath
|
||||||
};
|
};
|
||||||
textures.Add(normalizedFilePath);
|
textures.Add(normalizedFilePath);
|
||||||
}
|
}
|
||||||
@@ -965,10 +966,10 @@ namespace Barotrauma
|
|||||||
|
|
||||||
public void ResetZoom()
|
public void ResetZoom()
|
||||||
{
|
{
|
||||||
if (selectedTexture == null) { return; }
|
if (SelectedTexture == null) { return; }
|
||||||
var viewArea = GetViewArea;
|
var viewArea = GetViewArea;
|
||||||
float width = viewArea.Width / (float)selectedTexture.Texture.Width;
|
float width = viewArea.Width / (float)SelectedTexture.Width;
|
||||||
float height = viewArea.Height / (float)selectedTexture.Texture.Height;
|
float height = viewArea.Height / (float)SelectedTexture.Height;
|
||||||
zoom = Math.Min(1, Math.Min(width, height));
|
zoom = Math.Min(1, Math.Min(width, height));
|
||||||
zoomBar.BarScroll = GetBarScrollValue();
|
zoomBar.BarScroll = GetBarScrollValue();
|
||||||
viewAreaOffset = Point.Zero;
|
viewAreaOffset = Point.Zero;
|
||||||
|
|||||||
@@ -5,12 +5,10 @@ using Microsoft.Xna.Framework.Graphics;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using Microsoft.Xna.Framework.Input;
|
using Microsoft.Xna.Framework.Input;
|
||||||
using System.Threading.Tasks;
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
using System.IO;
|
using System.IO;
|
||||||
#else
|
#else
|
||||||
@@ -21,6 +19,12 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
class SubEditorScreen : EditorScreen
|
class SubEditorScreen : EditorScreen
|
||||||
{
|
{
|
||||||
|
public const int MaxStructures = 2000;
|
||||||
|
public const int MaxWalls = 500;
|
||||||
|
public const int MaxItems = 5000;
|
||||||
|
public const int MaxLights = 300;
|
||||||
|
public const int MaxShadowCastingLights = 60;
|
||||||
|
|
||||||
private static Submarine MainSub
|
private static Submarine MainSub
|
||||||
{
|
{
|
||||||
get => Submarine.MainSub;
|
get => Submarine.MainSub;
|
||||||
@@ -83,7 +87,11 @@ namespace Barotrauma
|
|||||||
NoCargoSpawnpoints,
|
NoCargoSpawnpoints,
|
||||||
NoBallastTag,
|
NoBallastTag,
|
||||||
NonLinkedGaps,
|
NonLinkedGaps,
|
||||||
TooManyLights
|
StructureCount,
|
||||||
|
WallCount,
|
||||||
|
ItemCount,
|
||||||
|
LightCount,
|
||||||
|
ShadowCastingLightCount
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector2 MouseDragStart = Vector2.Zero;
|
public static Vector2 MouseDragStart = Vector2.Zero;
|
||||||
@@ -102,7 +110,7 @@ namespace Barotrauma
|
|||||||
private bool wasSelectedBefore;
|
private bool wasSelectedBefore;
|
||||||
|
|
||||||
public GUIComponent TopPanel;
|
public GUIComponent TopPanel;
|
||||||
private GUIComponent showEntitiesPanel, entityCountPanel;
|
public GUIComponent showEntitiesPanel, entityCountPanel;
|
||||||
private readonly List<GUITickBox> showEntitiesTickBoxes = new List<GUITickBox>();
|
private readonly List<GUITickBox> showEntitiesTickBoxes = new List<GUITickBox>();
|
||||||
private readonly Dictionary<string, bool> hiddenSubCategories = new Dictionary<string, bool>();
|
private readonly Dictionary<string, bool> hiddenSubCategories = new Dictionary<string, bool>();
|
||||||
|
|
||||||
@@ -809,7 +817,7 @@ namespace Barotrauma
|
|||||||
var itemCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), itemCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight);
|
var itemCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), itemCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight);
|
||||||
itemCount.TextGetter = () =>
|
itemCount.TextGetter = () =>
|
||||||
{
|
{
|
||||||
itemCount.TextColor = ToolBox.GradientLerp(Item.ItemList.Count / 5000.0f, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red);
|
itemCount.TextColor = Item.ItemList.Count > MaxItems ? GUIStyle.Red : Color.Lerp(GUIStyle.Green, GUIStyle.Orange, Item.ItemList.Count / (float)MaxItems);
|
||||||
return Item.ItemList.Count.ToString();
|
return Item.ItemList.Count.ToString();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -818,8 +826,8 @@ namespace Barotrauma
|
|||||||
var structureCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), structureCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight);
|
var structureCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), structureCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight);
|
||||||
structureCount.TextGetter = () =>
|
structureCount.TextGetter = () =>
|
||||||
{
|
{
|
||||||
int count = (MapEntity.mapEntityList.Count - Item.ItemList.Count - Hull.HullList.Count - WayPoint.WayPointList.Count - Gap.GapList.Count);
|
int count = MapEntity.mapEntityList.Count - Item.ItemList.Count - Hull.HullList.Count - WayPoint.WayPointList.Count - Gap.GapList.Count;
|
||||||
structureCount.TextColor = ToolBox.GradientLerp(count / 1000.0f, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red);
|
structureCount.TextColor = count > MaxStructures ? GUIStyle.Red : Color.Lerp(GUIStyle.Green, GUIStyle.Orange, count / (float)MaxStructures);
|
||||||
return count.ToString();
|
return count.ToString();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -828,7 +836,7 @@ namespace Barotrauma
|
|||||||
var wallCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), wallCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight);
|
var wallCount = new GUITextBlock(new RectTransform(new Vector2(0.33f, 1.0f), wallCountText.RectTransform, Anchor.TopRight, Pivot.TopLeft), "", textAlignment: Alignment.CenterRight);
|
||||||
wallCount.TextGetter = () =>
|
wallCount.TextGetter = () =>
|
||||||
{
|
{
|
||||||
wallCount.TextColor = ToolBox.GradientLerp(Structure.WallList.Count / 500.0f, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red);
|
wallCount.TextColor = Structure.WallList.Count > MaxWalls ? GUIStyle.Red : Color.Lerp(GUIStyle.Green, GUIStyle.Orange, Structure.WallList.Count / (float)MaxWalls);
|
||||||
return Structure.WallList.Count.ToString();
|
return Structure.WallList.Count.ToString();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -843,7 +851,7 @@ namespace Barotrauma
|
|||||||
if (item.ParentInventory != null) { continue; }
|
if (item.ParentInventory != null) { continue; }
|
||||||
lightCount += item.GetComponents<LightComponent>().Count();
|
lightCount += item.GetComponents<LightComponent>().Count();
|
||||||
}
|
}
|
||||||
lightCountText.TextColor = ToolBox.GradientLerp(lightCount / 250.0f, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red);
|
lightCountText.TextColor = lightCount > MaxLights ? GUIStyle.Red : Color.Lerp(GUIStyle.Green, GUIStyle.Orange, lightCount / (float)MaxLights);
|
||||||
return lightCount.ToString();
|
return lightCount.ToString();
|
||||||
};
|
};
|
||||||
var shadowCastingLightCountLabel = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("SubEditorShadowCastingLights"),
|
var shadowCastingLightCountLabel = new GUITextBlock(new RectTransform(new Vector2(0.75f, 0.0f), paddedEntityCountPanel.RectTransform), TextManager.Get("SubEditorShadowCastingLights"),
|
||||||
@@ -857,7 +865,7 @@ namespace Barotrauma
|
|||||||
if (item.ParentInventory != null) { continue; }
|
if (item.ParentInventory != null) { continue; }
|
||||||
lightCount += item.GetComponents<LightComponent>().Count(l => l.CastShadows);
|
lightCount += item.GetComponents<LightComponent>().Count(l => l.CastShadows);
|
||||||
}
|
}
|
||||||
shadowCastingLightCountText.TextColor = ToolBox.GradientLerp(lightCount / 60.0f, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red);
|
shadowCastingLightCountText.TextColor = lightCount > MaxShadowCastingLights ? GUIStyle.Red : Color.Lerp(GUIStyle.Green, GUIStyle.Orange, lightCount / (float)MaxShadowCastingLights);
|
||||||
return lightCount.ToString();
|
return lightCount.ToString();
|
||||||
};
|
};
|
||||||
entityCountPanel.RectTransform.NonScaledSize =
|
entityCountPanel.RectTransform.NonScaledSize =
|
||||||
@@ -1448,7 +1456,7 @@ namespace Barotrauma
|
|||||||
case ".jpeg":
|
case ".jpeg":
|
||||||
if (saveFrame == null) { break; }
|
if (saveFrame == null) { break; }
|
||||||
|
|
||||||
Texture2D texture = Sprite.LoadTexture(filePath);
|
Texture2D texture = Sprite.LoadTexture(filePath, compress: false);
|
||||||
previewImage.Sprite = new Sprite(texture, null, null);
|
previewImage.Sprite = new Sprite(texture, null, null);
|
||||||
if (MainSub != null)
|
if (MainSub != null)
|
||||||
{
|
{
|
||||||
@@ -1548,7 +1556,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
foreach (GUIColorPicker colorPicker in msgBox.GetAllChildren<GUIColorPicker>())
|
foreach (GUIColorPicker colorPicker in msgBox.GetAllChildren<GUIColorPicker>())
|
||||||
{
|
{
|
||||||
colorPicker.DisposeTextures();
|
colorPicker.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
msgBox.Close();
|
msgBox.Close();
|
||||||
@@ -1827,6 +1835,21 @@ namespace Barotrauma
|
|||||||
modProject.Save(packagePath);
|
modProject.Save(packagePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!GameMain.DebugDraw)
|
||||||
|
{
|
||||||
|
if (Submarine.GetLightCount() > MaxLights)
|
||||||
|
{
|
||||||
|
new GUIMessageBox(TextManager.Get("error"), TextManager.GetWithVariable("subeditor.lightcounterror", "[max]", MaxShadowCastingLights.ToString()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Submarine.GetShadowCastingLightCount() > MaxShadowCastingLights)
|
||||||
|
{
|
||||||
|
new GUIMessageBox(TextManager.Get("error"), TextManager.GetWithVariable("subeditor.shadowcastinglightcounterror", "[max]", MaxShadowCastingLights.ToString()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(name))
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
{
|
{
|
||||||
GUI.AddMessage(TextManager.Get("SubNameMissingWarning"), GUIStyle.Red);
|
GUI.AddMessage(TextManager.Get("SubNameMissingWarning"), GUIStyle.Red);
|
||||||
@@ -3634,7 +3657,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
closeButton.OnClicked = (button, o) =>
|
closeButton.OnClicked = (button, o) =>
|
||||||
{
|
{
|
||||||
colorPicker.DisposeTextures();
|
colorPicker.Dispose();
|
||||||
msgBox.Close();
|
msgBox.Close();
|
||||||
|
|
||||||
Color newColor = SetColor(null);
|
Color newColor = SetColor(null);
|
||||||
@@ -3678,7 +3701,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
cancelButton.OnClicked = (button, o) =>
|
cancelButton.OnClicked = (button, o) =>
|
||||||
{
|
{
|
||||||
colorPicker.DisposeTextures();
|
colorPicker.Dispose();
|
||||||
msgBox.Close();
|
msgBox.Close();
|
||||||
|
|
||||||
foreach (var (e, color, prop) in entities)
|
foreach (var (e, color, prop) in entities)
|
||||||
|
|||||||
@@ -21,16 +21,16 @@ namespace Barotrauma
|
|||||||
private Item? miniMapItem;
|
private Item? miniMapItem;
|
||||||
|
|
||||||
private Submarine? submarine;
|
private Submarine? submarine;
|
||||||
private Character? dummyCharacter;
|
public static Character? dummyCharacter;
|
||||||
public static Effect BlueprintEffect = null!;
|
public static Effect? BlueprintEffect;
|
||||||
private GUIFrame container = null!;
|
private GUIFrame? container;
|
||||||
|
|
||||||
private TabMenu? tabMenu;
|
private TabMenu? tabMenu;
|
||||||
|
|
||||||
public TestScreen()
|
public TestScreen()
|
||||||
{
|
{
|
||||||
Cam = new Camera();
|
Cam = new Camera();
|
||||||
BlueprintEffect = GameMain.GameScreen.BlueprintEffect!;
|
BlueprintEffect = GameMain.GameScreen.BlueprintEffect;
|
||||||
|
|
||||||
new GUIButton(new RectTransform(new Point(256, 256), Frame.RectTransform), "Reload shader")
|
new GUIButton(new RectTransform(new Point(256, 256), Frame.RectTransform), "Reload shader")
|
||||||
{
|
{
|
||||||
@@ -38,7 +38,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
BlueprintEffect.Dispose();
|
BlueprintEffect.Dispose();
|
||||||
GameMain.Instance.Content.Unload();
|
GameMain.Instance.Content.Unload();
|
||||||
BlueprintEffect = GameMain.Instance.Content.Load<Effect>("Effects/blueprintshader_opengl")!;
|
BlueprintEffect = GameMain.Instance.Content.Load<Effect>("Effects/blueprintshader_opengl");
|
||||||
GameMain.GameScreen.BlueprintEffect = BlueprintEffect;
|
GameMain.GameScreen.BlueprintEffect = BlueprintEffect;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -47,21 +47,19 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override void Select()
|
public override void Select()
|
||||||
{
|
{
|
||||||
base.Select();
|
base.Select();
|
||||||
container = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: "InnerGlow", color: Color.Black);
|
container = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: "InnerGlow", color: Color.Black);
|
||||||
var tab = new GUIFrame(new RectTransform(Vector2.One, container.RectTransform), color: Color.Black * 0.9f);
|
var tab = new GUIFrame(new RectTransform(Vector2.One, container.RectTransform), color: Color.Black * 0.9f);
|
||||||
MedicalClinicUI clinic = new MedicalClinicUI(new MedicalClinic(null!), tab);
|
|
||||||
clinic.RequestLatestPending();
|
|
||||||
if (dummyCharacter is { Removed: false })
|
if (dummyCharacter is { Removed: false })
|
||||||
{
|
{
|
||||||
dummyCharacter?.Remove();
|
dummyCharacter?.Remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
// dummyCharacter = Character.Create(CharacterPrefab.HumanSpeciesName, Vector2.Zero, "", id: Entity.DummyID, hasAi: false);
|
dummyCharacter = Character.Create(CharacterPrefab.HumanSpeciesName, Vector2.Zero, "", id: Entity.DummyID, hasAi: false);
|
||||||
// dummyCharacter.Info.Job = new Job(JobPrefab.Prefabs.Where(jp => TalentTree.JobTalentTrees.ContainsKey(jp.Identifier)).GetRandom());
|
dummyCharacter.Info.Job = new Job(JobPrefab.Prefabs.Where(jp => TalentTree.JobTalentTrees.ContainsKey(jp.Identifier)).GetRandom(Rand.RandSync.Unsynced));
|
||||||
// dummyCharacter.Info.Name = "Galldren";
|
dummyCharacter.Info.Name = "Galldren";
|
||||||
// dummyCharacter.Inventory.CreateSlots();
|
dummyCharacter.Inventory.CreateSlots();
|
||||||
|
|
||||||
Character.Controlled = dummyCharacter;
|
Character.Controlled = dummyCharacter;
|
||||||
GameMain.World.ProcessChanges();
|
GameMain.World.ProcessChanges();
|
||||||
@@ -71,7 +69,8 @@ namespace Barotrauma
|
|||||||
public override void AddToGUIUpdateList()
|
public override void AddToGUIUpdateList()
|
||||||
{
|
{
|
||||||
Frame.AddToGUIUpdateList();
|
Frame.AddToGUIUpdateList();
|
||||||
container.AddToGUIUpdateList();
|
container?.AddToGUIUpdateList();
|
||||||
|
tabMenu?.AddToGUIUpdateList();
|
||||||
// CharacterHUD.AddToGUIUpdateList(dummyCharacter);
|
// CharacterHUD.AddToGUIUpdateList(dummyCharacter);
|
||||||
// dummyCharacter?.SelectedConstruction?.AddToGUIUpdateList();
|
// dummyCharacter?.SelectedConstruction?.AddToGUIUpdateList();
|
||||||
}
|
}
|
||||||
@@ -79,15 +78,13 @@ namespace Barotrauma
|
|||||||
public override void Update(double deltaTime)
|
public override void Update(double deltaTime)
|
||||||
{
|
{
|
||||||
base.Update(deltaTime);
|
base.Update(deltaTime);
|
||||||
tabMenu!.Update();
|
|
||||||
|
|
||||||
if (dummyCharacter is { } dummy)
|
if (dummyCharacter is { } dummy)
|
||||||
{
|
{
|
||||||
dummy.ControlLocalPlayer((float)deltaTime, Cam, false);
|
dummy.ControlLocalPlayer((float)deltaTime, Cam, false);
|
||||||
dummy.Control((float)deltaTime, Cam);
|
dummy.Control((float)deltaTime, Cam);
|
||||||
}
|
}
|
||||||
|
tabMenu?.Update((float)deltaTime);
|
||||||
GUI.Update((float)deltaTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
|
||||||
|
|||||||
@@ -342,9 +342,9 @@ namespace Barotrauma
|
|||||||
if (property.PropertyType == typeof(string) && value == null)
|
if (property.PropertyType == typeof(string) && value == null)
|
||||||
{
|
{
|
||||||
value = "";
|
value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
Identifier propertyTag = $"{entity.GetType().Name}.{property.PropertyInfo.Name}".ToIdentifier();
|
Identifier propertyTag = $"{property.PropertyInfo.DeclaringType.Name}.{property.PropertyInfo.Name}".ToIdentifier();
|
||||||
Identifier fallbackTag = property.PropertyInfo.Name.ToIdentifier();
|
Identifier fallbackTag = property.PropertyInfo.Name.ToIdentifier();
|
||||||
LocalizedString displayName =
|
LocalizedString displayName =
|
||||||
TextManager.Get(propertyTag, $"sp.{propertyTag}.name".ToIdentifier());
|
TextManager.Get(propertyTag, $"sp.{propertyTag}.name".ToIdentifier());
|
||||||
@@ -365,7 +365,7 @@ namespace Barotrauma
|
|||||||
{
|
{
|
||||||
displayName = property.Name.FormatCamelCaseWithSpaces();
|
displayName = property.Name.FormatCamelCaseWithSpaces();
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Editable editable = property.GetAttribute<Editable>();
|
InGameEditable editable = property.GetAttribute<InGameEditable>();
|
||||||
if (editable != null)
|
if (editable != null)
|
||||||
{
|
{
|
||||||
if (!MissingLocalizations.Contains($"sp.{propertyTag}.name|{displayName}"))
|
if (!MissingLocalizations.Contains($"sp.{propertyTag}.name|{displayName}"))
|
||||||
@@ -378,7 +378,11 @@ namespace Barotrauma
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalizedString toolTip = TextManager.Get($"sp.{propertyTag}.description", $"sp.{fallbackTag}.description");
|
LocalizedString toolTip = TextManager.Get($"sp.{propertyTag}.description");
|
||||||
|
if (toolTip.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
toolTip = TextManager.Get($"{propertyTag}.description", $"sp.{fallbackTag}.description");
|
||||||
|
}
|
||||||
|
|
||||||
if (toolTip == null)
|
if (toolTip == null)
|
||||||
{
|
{
|
||||||
@@ -1312,12 +1316,9 @@ namespace Barotrauma
|
|||||||
entity = e.Item;
|
entity = e.Item;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GameMain.Client != null)
|
if (GameMain.Client != null && entity is Item item)
|
||||||
{
|
{
|
||||||
if (entity is IClientSerializable clientSerializable)
|
GameMain.Client.CreateEntityEvent(item, new Item.ChangePropertyEventData(property));
|
||||||
{
|
|
||||||
GameMain.Client.CreateEntityEvent(clientSerializable, new object[] { NetEntityEvent.Type.ChangeProperty, property });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
-9
@@ -21,8 +21,8 @@ namespace Barotrauma.SpriteDeformations
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serialize("", IsPropertySaveable.Yes)]
|
[Serialize("", IsPropertySaveable.No)]
|
||||||
public string TypeName
|
public string Type
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
set;
|
||||||
@@ -35,7 +35,7 @@ namespace Barotrauma.SpriteDeformations
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name => $"Deformation ({TypeName})";
|
public string Name => $"Deformation ({Type})";
|
||||||
|
|
||||||
[Serialize(1.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0, MaxValueFloat = 10, DecimalCount = 2, ValueStep = 0.01f)]
|
[Serialize(1.0f, IsPropertySaveable.Yes), Editable(MinValueFloat = 0, MaxValueFloat = 10, DecimalCount = 2, ValueStep = 0.01f)]
|
||||||
public float Strength { get; private set; }
|
public float Strength { get; private set; }
|
||||||
@@ -85,11 +85,11 @@ namespace Barotrauma.SpriteDeformations
|
|||||||
|
|
||||||
public SpriteDeformationParams(XElement element)
|
public SpriteDeformationParams(XElement element)
|
||||||
{
|
{
|
||||||
if (element != null)
|
|
||||||
{
|
|
||||||
TypeName = element.GetAttributeString("type", "").ToLowerInvariant();
|
|
||||||
}
|
|
||||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
|
||||||
|
if (element != null && string.IsNullOrEmpty(Type))
|
||||||
|
{
|
||||||
|
Type = element.GetAttributeString("typename", string.Empty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ namespace Barotrauma.SpriteDeformations
|
|||||||
set { SetResolution(value); }
|
set { SetResolution(value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string TypeName => Params.TypeName;
|
public string TypeName => Params.Type;
|
||||||
|
|
||||||
public int Sync => Params.Sync;
|
public int Sync => Params.Sync;
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ namespace Barotrauma.SpriteDeformations
|
|||||||
|
|
||||||
if (newDeformation != null)
|
if (newDeformation != null)
|
||||||
{
|
{
|
||||||
newDeformation.Params.TypeName = typeName;
|
newDeformation.Params.Type = typeName;
|
||||||
}
|
}
|
||||||
return newDeformation;
|
return newDeformation;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -522,7 +522,7 @@ namespace Barotrauma.Steam
|
|||||||
UserData = tag
|
UserData = tag
|
||||||
};
|
};
|
||||||
tagBtn.RectTransform.NonScaledSize
|
tagBtn.RectTransform.NonScaledSize
|
||||||
= tagBtn.Font.MeasureString(tagBtn.Text).ToPoint() + new Point(GUI.IntScale(5));
|
= tagBtn.Font.MeasureString(tagBtn.Text).ToPoint() + new Point(GUI.IntScale(15), GUI.IntScale(5));
|
||||||
tagBtn.RectTransform.IsFixedSize = true;
|
tagBtn.RectTransform.IsFixedSize = true;
|
||||||
tagBtn.ClampMouseRectToParent = false;
|
tagBtn.ClampMouseRectToParent = false;
|
||||||
}
|
}
|
||||||
@@ -625,7 +625,7 @@ namespace Barotrauma.Steam
|
|||||||
#region Stats box
|
#region Stats box
|
||||||
var statsHorizontalLayout = new GUILayoutGroup(new RectTransform(Vector2.One, statsBox.RectTransform), isHorizontal: true);
|
var statsHorizontalLayout = new GUILayoutGroup(new RectTransform(Vector2.One, statsBox.RectTransform), isHorizontal: true);
|
||||||
var statsVertical0
|
var statsVertical0
|
||||||
= new GUILayoutGroup(new RectTransform((1.0f, 1.0f), statsHorizontalLayout.RectTransform));
|
= new GUILayoutGroup(new RectTransform((1.0f, 1.0f), statsHorizontalLayout.RectTransform), childAnchor: Anchor.TopCenter);
|
||||||
|
|
||||||
statFrame("", ""); //padding
|
statFrame("", ""); //padding
|
||||||
|
|
||||||
@@ -680,7 +680,7 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
var tagsLabel = new GUITextBlock(new RectTransform((1.0f, 0.12f), statsVertical0.RectTransform),
|
var tagsLabel = new GUITextBlock(new RectTransform((1.0f, 0.12f), statsVertical0.RectTransform),
|
||||||
TextManager.Get("WorkshopItemTags"), font: GUIStyle.SubHeadingFont);
|
TextManager.Get("WorkshopItemTags"), font: GUIStyle.SubHeadingFont);
|
||||||
CreateTagsList(workshopItem.Tags.ToIdentifiers(), new RectTransform((1.0f, 0.3f), statsVertical0.RectTransform), canBeFocused: false);
|
CreateTagsList(workshopItem.Tags.ToIdentifiers(), new RectTransform((0.97f, 0.3f), statsVertical0.RectTransform), canBeFocused: false);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var descriptionListBox = new GUIListBox(new RectTransform((1.0f, 0.38f), verticalLayout.RectTransform));
|
var descriptionListBox = new GUIListBox(new RectTransform((1.0f, 0.38f), verticalLayout.RectTransform));
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ namespace Barotrauma.Steam
|
|||||||
if (GameMain.Client == null)
|
if (GameMain.Client == null)
|
||||||
{
|
{
|
||||||
LeaveLobby();
|
LeaveLobby();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lobbyState == LobbyState.NotConnected)
|
if (lobbyState == LobbyState.NotConnected)
|
||||||
@@ -83,7 +84,7 @@ namespace Barotrauma.Steam
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentPackages = ContentPackageManager.EnabledPackages.All.Where(cp => cp.HasMultiplayerIncompatibleContent);
|
var contentPackages = ContentPackageManager.EnabledPackages.All.Where(cp => cp.HasMultiplayerSyncedContent);
|
||||||
|
|
||||||
currentLobby?.SetData("name", serverSettings.ServerName);
|
currentLobby?.SetData("name", serverSettings.ServerName);
|
||||||
currentLobby?.SetData("playercount", (GameMain.Client?.ConnectedClients?.Count ?? 0).ToString());
|
currentLobby?.SetData("playercount", (GameMain.Client?.ConnectedClients?.Count ?? 0).ToString());
|
||||||
|
|||||||
@@ -357,21 +357,31 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
private IEnumerable<CoroutineStatus> MessageBoxCoroutine(Func<GUITextBlock, GUIMessageBox, IEnumerable<CoroutineStatus>> subcoroutine)
|
private IEnumerable<CoroutineStatus> MessageBoxCoroutine(Func<GUITextBlock, GUIMessageBox, IEnumerable<CoroutineStatus>> subcoroutine)
|
||||||
{
|
{
|
||||||
var messageBox = new GUIMessageBox("", "", relativeSize: (0.4f, 0.4f), buttons: new [] { TextManager.Get("Cancel") });
|
var messageBox = new GUIMessageBox("", "...", buttons: new [] { TextManager.Get("Cancel") });
|
||||||
messageBox.Buttons[0].OnClicked = (button, o) =>
|
messageBox.Buttons[0].OnClicked = (button, o) =>
|
||||||
{
|
{
|
||||||
messageBox.Close();
|
messageBox.Close();
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
var currentStepText = new GUITextBlock(new RectTransform((1.0f, 0.8f), messageBox.InnerFrame.RectTransform),
|
var coroutineEval = subcoroutine(messageBox.Text, messageBox);
|
||||||
"...", font: GUIStyle.Font)
|
while (true)
|
||||||
{
|
|
||||||
CanBeFocused = false
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var status in subcoroutine(currentStepText, messageBox))
|
|
||||||
{
|
{
|
||||||
|
bool moveNext = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
moveNext = coroutineEval.GetEnumerator().MoveNext();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
DebugConsole.ThrowError($"{e.Message} {e.StackTrace.CleanupStackTrace()}");
|
||||||
|
messageBox.Close();
|
||||||
|
}
|
||||||
|
if (!moveNext)
|
||||||
|
{
|
||||||
|
messageBox.Close();
|
||||||
|
}
|
||||||
|
var status = coroutineEval.GetEnumerator().Current;
|
||||||
if (messageBox.Closed)
|
if (messageBox.Closed)
|
||||||
{
|
{
|
||||||
yield return CoroutineStatus.Success;
|
yield return CoroutineStatus.Success;
|
||||||
@@ -410,7 +420,7 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
SteamManager.Workshop.ForceRedownload(workshopItem);
|
SteamManager.Workshop.ForceRedownload(workshopItem);
|
||||||
}
|
}
|
||||||
currentStepText.Text = $"Downloading {Percentage(workshopItem.DownloadAmount)}";
|
currentStepText.Text = TextManager.GetWithVariable("PublishPopupDownload", "[percentage]", Percentage(workshopItem.DownloadAmount));
|
||||||
yield return new WaitForSeconds(0.5f);
|
yield return new WaitForSeconds(0.5f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -426,7 +436,7 @@ namespace Barotrauma.Steam
|
|||||||
});
|
});
|
||||||
while (!ContentPackageManager.WorkshopPackages.Any(p => p.SteamWorkshopId == workshopItem.Id))
|
while (!ContentPackageManager.WorkshopPackages.Any(p => p.SteamWorkshopId == workshopItem.Id))
|
||||||
{
|
{
|
||||||
currentStepText.Text = $"Installing";
|
currentStepText.Text = TextManager.Get("PublishPopupInstall");
|
||||||
yield return new WaitForSeconds(0.5f);
|
yield return new WaitForSeconds(0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,7 +454,7 @@ namespace Barotrauma.Steam
|
|||||||
});
|
});
|
||||||
while (!localCopyMade)
|
while (!localCopyMade)
|
||||||
{
|
{
|
||||||
currentStepText.Text = $"Creating local copy";
|
currentStepText.Text = TextManager.Get("PublishPopupCreateLocal");
|
||||||
yield return new WaitForSeconds(0.5f);
|
yield return new WaitForSeconds(0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,47 +467,62 @@ namespace Barotrauma.Steam
|
|||||||
GUITextBlock currentStepText, GUIMessageBox messageBox,
|
GUITextBlock currentStepText, GUIMessageBox messageBox,
|
||||||
string modVersion, Steamworks.Ugc.Editor editor, ContentPackage localPackage)
|
string modVersion, Steamworks.Ugc.Editor editor, ContentPackage localPackage)
|
||||||
{
|
{
|
||||||
|
if (!SteamManager.IsInitialized)
|
||||||
|
{
|
||||||
|
yield return CoroutineStatus.Failure;
|
||||||
|
}
|
||||||
|
|
||||||
bool stagingReady = false;
|
bool stagingReady = false;
|
||||||
|
Exception? stagingException = null;
|
||||||
TaskPool.Add("CreatePublishStagingCopy",
|
TaskPool.Add("CreatePublishStagingCopy",
|
||||||
SteamManager.Workshop.CreatePublishStagingCopy(modVersion, localPackage),
|
SteamManager.Workshop.CreatePublishStagingCopy(modVersion, localPackage),
|
||||||
(t) =>
|
(t) =>
|
||||||
{
|
{
|
||||||
Exception? exception = t.Exception?.InnerException ?? t.Exception;
|
|
||||||
if (exception != null)
|
|
||||||
{
|
|
||||||
throw new Exception($"Failed to create staging copy: {exception.Message} {exception.StackTrace}");
|
|
||||||
}
|
|
||||||
stagingReady = true;
|
stagingReady = true;
|
||||||
|
stagingException = t.Exception?.GetInnermost();
|
||||||
});
|
});
|
||||||
currentStepText.Text = "Copying item to staging folder...";
|
currentStepText.Text = TextManager.Get("PublishPopupStaging");
|
||||||
while (!stagingReady) { yield return new WaitForSeconds(0.5f); }
|
while (!stagingReady) { yield return new WaitForSeconds(0.5f); }
|
||||||
|
|
||||||
|
if (stagingException != null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Failed to create staging copy: {stagingException.Message} {stagingException.StackTrace.CleanupStackTrace()}");
|
||||||
|
}
|
||||||
|
|
||||||
editor = editor
|
editor = editor
|
||||||
.WithContent(SteamManager.Workshop.PublishStagingDir)
|
.WithContent(SteamManager.Workshop.PublishStagingDir)
|
||||||
.ForAppId(SteamManager.AppID);
|
.ForAppId(SteamManager.AppID);
|
||||||
|
|
||||||
messageBox.Buttons[0].Enabled = false;
|
messageBox.Buttons[0].Enabled = false;
|
||||||
Steamworks.Ugc.PublishResult? result = null;
|
Steamworks.Ugc.PublishResult? result = null;
|
||||||
|
Exception? resultException = null;
|
||||||
TaskPool.Add($"Publishing {localPackage.Name} ({localPackage.SteamWorkshopId})",
|
TaskPool.Add($"Publishing {localPackage.Name} ({localPackage.SteamWorkshopId})",
|
||||||
editor.SubmitAsync(),
|
editor.SubmitAsync(),
|
||||||
(t) =>
|
t =>
|
||||||
{
|
{
|
||||||
result = ((Task<Steamworks.Ugc.PublishResult>)t).Result;
|
t.TryGetResult(out result);
|
||||||
|
resultException = t.Exception?.GetInnermost();
|
||||||
});
|
});
|
||||||
currentStepText.Text = "Submitting item to the Workshop...";
|
currentStepText.Text = TextManager.Get("PublishPopupSubmit");
|
||||||
while (!result.HasValue) { yield return new WaitForSeconds(0.5f); }
|
while (!result.HasValue && resultException is null) { yield return new WaitForSeconds(0.5f); }
|
||||||
|
|
||||||
if (result.Value.Success)
|
if (result is { Success: true })
|
||||||
{
|
{
|
||||||
var resultId = result.Value.FileId;
|
var resultId = result.Value.FileId;
|
||||||
Steamworks.Ugc.Item resultItem = new Steamworks.Ugc.Item(resultId);
|
Steamworks.Ugc.Item resultItem = new Steamworks.Ugc.Item(resultId);
|
||||||
SteamManager.Workshop.ForceRedownload(resultItem);
|
Task downloadTask = SteamManager.Workshop.ForceRedownload(resultItem);
|
||||||
while (!resultItem.IsInstalled)
|
while (!resultItem.IsInstalled && !downloadTask.IsCompleted)
|
||||||
{
|
{
|
||||||
currentStepText.Text = $"Downloading {Percentage(resultItem.DownloadAmount)}";
|
currentStepText.Text = TextManager.GetWithVariable("PublishPopupDownload", "[percentage]", Percentage(resultItem.DownloadAmount));
|
||||||
yield return new WaitForSeconds(0.5f);
|
yield return new WaitForSeconds(0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!resultItem.IsInstalled)
|
||||||
|
{
|
||||||
|
throw new Exception($"Failed to install item: download task ended with status {downloadTask.Status}, " +
|
||||||
|
$"exception was {downloadTask.Exception?.GetInnermost()?.ToString().CleanupStackTrace() ?? "[NULL]"}");
|
||||||
|
}
|
||||||
|
|
||||||
bool installed = false;
|
bool installed = false;
|
||||||
TaskPool.Add(
|
TaskPool.Add(
|
||||||
"InstallNewlyPublished",
|
"InstallNewlyPublished",
|
||||||
@@ -508,7 +533,7 @@ namespace Barotrauma.Steam
|
|||||||
});
|
});
|
||||||
while (!installed)
|
while (!installed)
|
||||||
{
|
{
|
||||||
currentStepText.Text = $"Installing";
|
currentStepText.Text = TextManager.Get("PublishPopupInstall");
|
||||||
yield return new WaitForSeconds(0.5f);
|
yield return new WaitForSeconds(0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -524,8 +549,19 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
SteamManager.OverlayCustomURL(resultItem.Url);
|
SteamManager.OverlayCustomURL(resultItem.Url);
|
||||||
}
|
}
|
||||||
|
new GUIMessageBox(string.Empty, TextManager.GetWithVariable("workshopitempublished", "[itemname]", localPackage.Name));
|
||||||
}
|
}
|
||||||
|
else if (resultException != null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Failed to publish item: {resultException.Message} {resultException.StackTrace.CleanupStackTrace()}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new GUIMessageBox(TextManager.Get("error"), TextManager.GetWithVariable("workshopitempublishfailed", "[itemname]", localPackage.Name));
|
||||||
|
}
|
||||||
|
|
||||||
SteamManager.Workshop.DeletePublishStagingCopy();
|
SteamManager.Workshop.DeletePublishStagingCopy();
|
||||||
|
messageBox.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ namespace Barotrauma.Steam
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static int Round(float v) => (int)MathF.Round(v);
|
private static int Round(float v) => (int)MathF.Round(v);
|
||||||
private static string Percentage(float v) => $"{Round(v * 100)}%";
|
private static string Percentage(float v) => $"{Round(v * 100)}";
|
||||||
|
|
||||||
private struct ActionCarrier
|
private struct ActionCarrier
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
|
using Barotrauma.IO;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using RestSharp;
|
using RestSharp;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Barotrauma.IO;
|
|
||||||
|
|
||||||
namespace Barotrauma.Steam
|
namespace Barotrauma.Steam
|
||||||
{
|
{
|
||||||
@@ -180,8 +179,10 @@ namespace Barotrauma.Steam
|
|||||||
await CopyDirectory(contentPackage.Dir, contentPackage.Name, Path.GetDirectoryName(contentPackage.Path)!, PublishStagingDir);
|
await CopyDirectory(contentPackage.Dir, contentPackage.Name, Path.GetDirectoryName(contentPackage.Path)!, PublishStagingDir);
|
||||||
|
|
||||||
//Load filelist.xml and write the hash into it so anyone downloading this mod knows what it should be
|
//Load filelist.xml and write the hash into it so anyone downloading this mod knows what it should be
|
||||||
ModProject modProject = new ModProject(contentPackage);
|
ModProject modProject = new ModProject(contentPackage)
|
||||||
modProject.ModVersion = modVersion;
|
{
|
||||||
|
ModVersion = modVersion
|
||||||
|
};
|
||||||
modProject.Save(Path.Combine(PublishStagingDir, ContentPackage.FileListFileName));
|
modProject.Save(Path.Combine(PublishStagingDir, ContentPackage.FileListFileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using System;
|
|
||||||
using Barotrauma.Extensions;
|
using Barotrauma.Extensions;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Xml.Linq;
|
|
||||||
using Barotrauma.IO;
|
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
|
||||||
using ItemOrPackage = Barotrauma.Either<Steamworks.Ugc.Item, Barotrauma.ContentPackage>;
|
using ItemOrPackage = Barotrauma.Either<Steamworks.Ugc.Item, Barotrauma.ContentPackage>;
|
||||||
|
|
||||||
namespace Barotrauma.Steam
|
namespace Barotrauma.Steam
|
||||||
@@ -25,12 +20,12 @@ namespace Barotrauma.Steam
|
|||||||
Publish
|
Publish
|
||||||
}
|
}
|
||||||
|
|
||||||
private GUILayoutGroup tabber;
|
private readonly GUILayoutGroup tabber;
|
||||||
private Dictionary<Tab, (GUIButton Button, GUIFrame Content)> tabContents;
|
private readonly Dictionary<Tab, (GUIButton Button, GUIFrame Content)> tabContents;
|
||||||
|
|
||||||
private GUIFrame contentFrame;
|
private readonly GUIFrame contentFrame;
|
||||||
|
|
||||||
private CorePackage enabledCorePackage => enabledCoreDropdown.SelectedData as CorePackage ?? throw new Exception("Valid core package not selected");
|
private CorePackage EnabledCorePackage => enabledCoreDropdown.SelectedData as CorePackage ?? throw new Exception("Valid core package not selected");
|
||||||
|
|
||||||
private readonly GUIDropDown enabledCoreDropdown;
|
private readonly GUIDropDown enabledCoreDropdown;
|
||||||
private readonly GUIListBox enabledRegularModsList;
|
private readonly GUIListBox enabledRegularModsList;
|
||||||
@@ -173,7 +168,7 @@ namespace Barotrauma.Steam
|
|||||||
|
|
||||||
to.DraggedElement = draggedElement;
|
to.DraggedElement = draggedElement;
|
||||||
|
|
||||||
to.BarScroll = to.BarScroll * (oldCount / newCount);
|
to.BarScroll *= (oldCount / newCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,7 +362,8 @@ namespace Barotrauma.Steam
|
|||||||
{
|
{
|
||||||
ToolBox.OpenFileWithShell(mod.Dir);
|
ToolBox.OpenFileWithShell(mod.Dir);
|
||||||
return false;
|
return false;
|
||||||
}
|
},
|
||||||
|
ToolTip = TextManager.Get("OpenLocalModInExplorer")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (ContentPackageManager.WorkshopPackages.Contains(mod))
|
else if (ContentPackageManager.WorkshopPackages.Contains(mod))
|
||||||
@@ -386,8 +382,13 @@ namespace Barotrauma.Steam
|
|||||||
onInstalledInfoButtonHit(item.Value);
|
onInstalledInfoButtonHit(item.Value);
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
},
|
||||||
|
ToolTip = TextManager.Get("ViewModDetails")
|
||||||
};
|
};
|
||||||
|
if (!SteamManager.IsInitialized)
|
||||||
|
{
|
||||||
|
infoButton.Enabled = false;
|
||||||
|
}
|
||||||
TaskPool.Add(
|
TaskPool.Add(
|
||||||
$"DetermineUpdateRequired{mod.SteamWorkshopId}",
|
$"DetermineUpdateRequired{mod.SteamWorkshopId}",
|
||||||
mod.IsUpToDate(),
|
mod.IsUpToDate(),
|
||||||
@@ -398,6 +399,7 @@ namespace Barotrauma.Steam
|
|||||||
if (!isUpToDate)
|
if (!isUpToDate)
|
||||||
{
|
{
|
||||||
infoButton.ApplyStyle(GUIStyle.ComponentStyles["WorkshopMenu.InfoButtonUpdate"]);
|
infoButton.ApplyStyle(GUIStyle.ComponentStyles["WorkshopMenu.InfoButtonUpdate"]);
|
||||||
|
infoButton.ToolTip = TextManager.Get("ViewModDetailsUpdateAvailable");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -421,20 +423,26 @@ namespace Barotrauma.Steam
|
|||||||
private void CreatePopularModsTab(out GUIListBox popularModsList)
|
private void CreatePopularModsTab(out GUIListBox popularModsList)
|
||||||
{
|
{
|
||||||
GUIFrame content = CreateNewContentFrame(Tab.PopularMods);
|
GUIFrame content = CreateNewContentFrame(Tab.PopularMods);
|
||||||
|
if (!SteamManager.IsInitialized)
|
||||||
|
{
|
||||||
|
tabContents[Tab.PopularMods].Button.Enabled = false;
|
||||||
|
}
|
||||||
CreateWorkshopItemList(content, out _, out popularModsList, onSelected: PopulateFrameWithItemInfo);
|
CreateWorkshopItemList(content, out _, out popularModsList, onSelected: PopulateFrameWithItemInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreatePublishTab(out GUIListBox selfModsList)
|
private void CreatePublishTab(out GUIListBox selfModsList)
|
||||||
{
|
{
|
||||||
GUIFrame content = CreateNewContentFrame(Tab.Publish);
|
GUIFrame content = CreateNewContentFrame(Tab.Publish);
|
||||||
|
if (!SteamManager.IsInitialized)
|
||||||
|
{
|
||||||
|
tabContents[Tab.Publish].Button.Enabled = false;
|
||||||
|
}
|
||||||
CreateWorkshopItemOrPackageList(content, out _, out selfModsList, onSelected: PopulatePublishTab);
|
CreateWorkshopItemOrPackageList(content, out _, out selfModsList, onSelected: PopulatePublishTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Apply()
|
public void Apply()
|
||||||
{
|
{
|
||||||
ContentPackageManager.EnabledPackages.SetCore(enabledCorePackage);
|
ContentPackageManager.EnabledPackages.SetCore(EnabledCorePackage);
|
||||||
ContentPackageManager.EnabledPackages.SetRegular(enabledRegularModsList.Content.Children
|
ContentPackageManager.EnabledPackages.SetRegular(enabledRegularModsList.Content.Children
|
||||||
.Where(c => c.UserData is RegularPackage).Select(c => (RegularPackage)c.UserData).ToArray());
|
.Where(c => c.UserData is RegularPackage).Select(c => (RegularPackage)c.UserData).ToArray());
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user