Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dgarroDC committed May 21, 2022
0 parents commit 630ab2d
Show file tree
Hide file tree
Showing 16 changed files with 1,064 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
packages
.vs
bin
obj
.idea
Build
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 Ricardo Lopes

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Suit Log by Damián Garro

![thumbnail](images/thumbnail.webp)

Tired of having to go to the ship again and again just to check any data in the Ship Log? Not anymore! With Suit Log you just need to **suit up**, go out to have your adventures without annoying interruptions and check the data you want at any time!

You don't have to learn anything to use this new interface, the controls are the same as in the Ship Log! Just use the autopilot key to open it (**X key** in the gamepad or **up D-pad button** in the gamepad by default). You'll have everything you need right there: entries with their photos, "icons", marking location in HUD...

And all of this displayed in a diegetic interface that shares design with the other HUD elements displayed on the helmet, intended to feel like a vanilla feature and not an external add-on!

*Note:* Only Map Mode is included in Suit Log, you will still need the to use the Ship Log for the Rumor Mode. The "map" is different here though, the planets (and other locations) are displayed as a list, where you can select one to view the list of its entries.

![poem|width=400px](images/poem.jpg)

Entries you read will be marked as read the same way the Ship Log does it, although it is planned to make this optional in a future update. Other future updates could include the option of pausing the game while using the Suit Log and disabling the display of entry photos if you want a simplified alternative.

If you want to use the Suit Log in the few places where you can't have the Suit on, I recommend using the [Cheat And Debug Menu](https://outerwildsmods.com/mods/cheatanddebugmenu/) mod, pressing the **F2 key** to put on the suit, although I may add the option to be able to open the Suit Log even without the suit as a *cheat mode*.

Please, I'd be happy to receive any suggestions and bug reports on [GitHub](https://github.com/dgarroDC/SuitLog/issues) or in the [Outer Wilds Modding Discord Server](https://discord.gg/9vE5aHxcF9). Thanks.

## Compatibility and interactions with other mods

* [Ship Log Slide Reel Player](https://outerwildsmods.com/mods/shiplogslidereelplayer/): The Suit Log doesn't display the reels, but the mods are compatible: you should be able to run the game with both mods enabled without issues but you would need to use the Ship Log to view the reels (a future update could integrate that feature to the Suit Log)
* [Archaeologist Achievement Helper](https://outerwildsmods.com/mods/archaeologistachievementhelper/): The mods are compatible and if you run the game with Suit Log and this helper mod, the later would add the *"There's more to explore here."* mark and text to entries to both the Ship Log and Suit Log. However, the *"Show all missing facts"* optional feature only applies to the Ship Logs and the Suit Log would be unaffected by this. TODO: VERIFY THIS
25 changes: 25 additions & 0 deletions SuitLog.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30204.135
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SuitLog", "SuitLog\SuitLog.csproj", "{8A39F9E7-1A89-430C-9C3E-BDFB3B7E17DF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8A39F9E7-1A89-430C-9C3E-BDFB3B7E17DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A39F9E7-1A89-430C-9C3E-BDFB3B7E17DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A39F9E7-1A89-430C-9C3E-BDFB3B7E17DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A39F9E7-1A89-430C-9C3E-BDFB3B7E17DF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3C8C943F-F2D5-4733-9CD6-9DD77B9FA9A1}
EndGlobalSection
EndGlobal
212 changes: 212 additions & 0 deletions SuitLog/DescriptionField.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.PlayerLoop;
using UnityEngine.UI;

namespace SuitLog
{
public class DescriptionField
{
private OWAudioSource _audioSource;
private RectTransform _descField;
private RectTransform _factList;
private ShipLogFactListItem[] _items;
private float _origYPos;
private int _displayCount = 0;
private bool _visible;
private CanvasGroupAnimator _animator;
private Vector3 _closeScale;

private ScreenPrompt _scrollPromptGamepad;
private ScreenPrompt _scrollPromptKbm;

internal DescriptionField(GameObject suitLog)
{
// I should probably reuse ShipLogEntryDescriptionField...
GameObject descFieldObject = new GameObject("DescriptionField");
_descField = descFieldObject.AddComponent<RectTransform>();
SuitLog.SetParent(_descField, suitLog.transform);
_descField.sizeDelta = new Vector2(600, 290);
_descField.anchoredPosition = new Vector2(0, -425);
_descField.anchorMin = new Vector2(0, 1);
_descField.anchorMax = new Vector2(1, 1);
_descField.pivot = new Vector2(0, 1);
descFieldObject.AddComponent<RectMask2D>();
descFieldObject.AddComponent<Image>().color = new Color(0.5468f, 0.816f, 0.9057f, 0.18f);

GameObject factListObject = new GameObject("FactList");
_factList = factListObject.AddComponent<RectTransform>();
SuitLog.SetParent(_factList, _descField);
_factList.sizeDelta = new Vector2(0, 30000); // ?
_factList.anchoredPosition = new Vector2(0, 0);
_factList.anchorMin = new Vector2(0, 0);
_factList.anchorMax = new Vector2(1, 1);
_factList.pivot = new Vector2(0, 1);
_origYPos = _factList.anchoredPosition.y;
VerticalLayoutGroup verticalLayoutGroup = factListObject.AddComponent<VerticalLayoutGroup>();
verticalLayoutGroup.childForceExpandHeight = false;

_items = new ShipLogFactListItem[10];
for (int i = 0; i < _items.Length; i++)
{
Text text = SuitLog.CreateText();
SuitLog.SetParent(text.transform, _factList);
text.horizontalOverflow = HorizontalWrapMode.Wrap;
text.GetComponent<RectTransform>().pivot = new Vector2(0, 1);
ShipLogFactListItem item = text.gameObject.AddComponent<ShipLogFactListItem>();
item._text = text;
// Set active to avoid NRE on first UpdatePromptsVisibility?
item.gameObject.SetActive(true);
_items[i] = item;
}

descFieldObject.AddComponent<CanvasGroup>();
_animator = descFieldObject.AddComponent<CanvasGroupAnimator>();
_closeScale = new Vector3(1f, 0f, 1f);
_animator.SetImmediate(0f, new Vector3(1f, 0f, 1f)); // Start closed
_visible = false;

GameObject revealAudio = GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/DescriptionField/TextRevealAudioSource");
GameObject audioSourceObject = Object.Instantiate(revealAudio);
SuitLog.SetParent(audioSourceObject.transform, descFieldObject.transform);
_audioSource = audioSourceObject.GetComponent<OWAudioSource>();
_audioSource.SetTrack(OWAudioMixer.TrackName.Player); // Not sure if we need this
}

public void Update()
{
UpdateTextReveal();
UpdateScroll();
}

private void UpdateTextReveal()
{
bool revealing = false;
foreach (ShipLogFactListItem item in _items)
{
if (item.UpdateTextReveal())
{
revealing = true;
}
if (item._fact != null)
{
item._text.text = "- " + item._text.text;
}
}

if (revealing && !_audioSource.isPlaying)
{
_audioSource.Play();
}
else if (!revealing && _audioSource.isPlaying)
{
_audioSource.Stop();
}
}

public void UpdateScroll()
{
if (!_visible) return; // This case shouldn't be possible because of _isEntryMenuOpen = false
bool usingGamepad = OWInput.UsingGamepad();
float scroll;
if (usingGamepad)
{
scroll = Input.GetValue(Input.Action.ScrollFactsGamepad) * Time.unscaledDeltaTime * 300f;
}
else
{
scroll = Input.GetValue(Input.Action.ScrollFactsKbm) * Time.unscaledDeltaTime * 300f;
}
Vector2 anchoredPosition = _factList.anchoredPosition;
float targetScroll = anchoredPosition.y - scroll;
float maxScroll = GetMaxScroll();
anchoredPosition.y = Mathf.Clamp(targetScroll, _origYPos, _origYPos - maxScroll);
_factList.anchoredPosition = anchoredPosition;
}

private float GetMaxScroll()
{
return Mathf.Min(0f, GetListBottomPos() + _descField.rect.height);
}

public void SetupPrompts()
{
string prompt = UITextLibrary.GetString(UITextType.LogScrollTextPrompt);
_scrollPromptGamepad = new ScreenPrompt(Input.PromptCommands(Input.Action.ScrollFactsGamepad), prompt);
_scrollPromptKbm = new ScreenPrompt(Input.PromptCommands(Input.Action.ScrollFactsKbm), prompt);
Locator.GetPromptManager().AddScreenPrompt(_scrollPromptGamepad, PromptPosition.UpperRight);
Locator.GetPromptManager().AddScreenPrompt(_scrollPromptKbm, PromptPosition.UpperRight);
// _scrollPromptGamepad.SetDisplayState(ScreenPrompt.DisplayState.Attention);
// _scrollPromptKbm.SetDisplayState(ScreenPrompt.DisplayState.Attention);
}

public void UpdatePromptsVisibility()
{
bool usingGamepad = OWInput.UsingGamepad();
bool scrollable = GetMaxScroll() < 0f; // Is this ok?
_scrollPromptGamepad.SetVisibility(_visible && scrollable && usingGamepad);
_scrollPromptKbm.SetVisibility(_visible && scrollable && !usingGamepad);
}

public void HideAllPrompts()
{
_scrollPromptGamepad.SetVisibility(false);
_scrollPromptKbm.SetVisibility(false);
}

public void SetEntry(ShipLogEntry entry)
{
ResetListPos();
List<ShipLogFact> facts = entry.GetFactsForDisplay();
for (int i = 0; i < _items.Length; i++)
{
if (i < facts.Count)
{
_items[i].DisplayFact(facts[i]);
_items[i].StartTextReveal();
}
else
{
_items[i].Clear();
}
}

_displayCount = facts.Count;

if (entry.HasMoreToExplore())
{
_items[_displayCount].DisplayText("- " + UITextLibrary.GetString(UITextType.ShipLogMoreThere));
}
}

public void Open()
{
_visible = true;
_animator.AnimateTo( 1, Vector3.one , SuitLog.OpenAnimationDuration);
}

public void Close()
{
_visible = false;
_animator.AnimateTo( 0, _closeScale, SuitLog.CloseAnimationDuration);
if (_audioSource.isPlaying)
{
_audioSource.Stop();
}
}

private void ResetListPos()
{
Vector2 anchoredPosition = _factList.anchoredPosition;
anchoredPosition.y = 0;
_factList.anchoredPosition = anchoredPosition;
}

private float GetListBottomPos()
{
if (_displayCount <= 0) return 0f; // Is this case possible?
ShipLogFactListItem lastItem = _items[_displayCount - 1];
return lastItem.GetPosition().y - lastItem.GetHeight();
}
}
}
84 changes: 84 additions & 0 deletions SuitLog/Input.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using UnityEngine.Assertions;

namespace SuitLog;

public static class Input
{
public enum Action
{
OpenSuitLog,
CloseSuitLog,
ViewEntries,
CloseEntries,
MarkEntryOnHUD,
ListUp,
ListDown,
ScrollFactsKbm,
ScrollFactsGamepad
}

private static List<IInputCommands> GetInputCommands(Action action)
{
switch (action)
{
case Action.OpenSuitLog:
return new List<IInputCommands>{InputLibrary.autopilot};
// The rest of actions use the same input commands as the ship log
case Action.CloseSuitLog:
return new List<IInputCommands>{InputLibrary.cancel};
case Action.ViewEntries:
return new List<IInputCommands>{InputLibrary.interact};
case Action.CloseEntries:
// The prompt will show the cancel command but interact is also possible
return new List<IInputCommands>{InputLibrary.cancel, InputLibrary.interact};
case Action.MarkEntryOnHUD:
return new List<IInputCommands>{InputLibrary.markEntryOnHUD};
case Action.ListUp:
return new List<IInputCommands>{InputLibrary.up, InputLibrary.up2};
case Action.ListDown:
return new List<IInputCommands>{InputLibrary.down, InputLibrary.down2};
case Action.ScrollFactsKbm:
return new List<IInputCommands>{InputLibrary.toolOptionY};
case Action.ScrollFactsGamepad:
return new List<IInputCommands>{InputLibrary.scrollLogText};
}

return null;
}

private static bool CheckAction(Action action, Func<IInputCommands, bool> checker)
{
foreach (IInputCommands commands in GetInputCommands(action))
{
if (checker.Invoke(commands))
{
return true;
}
}

return false;
}

public static IInputCommands PromptCommands(Action action)
{
return GetInputCommands(action)[0];
}

public static bool IsNewlyPressed(Action action)
{
return CheckAction(action, commands => OWInput.IsNewlyPressed(commands));
}

public static bool IsPressed(Action action)
{
return CheckAction(action, commands => OWInput.IsPressed(commands));
}

public static float GetValue(Action action)
{
List<IInputCommands> commands = GetInputCommands(action);
return OWInput.GetValue(commands[0]);
}
}
Loading

0 comments on commit 630ab2d

Please sign in to comment.