Unstable 0.17.0.0
This commit is contained in:
-683
@@ -1,683 +0,0 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
class BasicTutorial : ScenarioTutorial
|
||||
{
|
||||
public BasicTutorial(XElement element)
|
||||
: base(element)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerable<CoroutineStatus> UpdateState()
|
||||
{
|
||||
Character Controlled = Character.Controlled;
|
||||
if (Controlled == null) yield return CoroutineStatus.Success;
|
||||
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
var wire = item.GetComponent<Wire>();
|
||||
if (wire != null && wire.Connections.Any(c => c != null))
|
||||
{
|
||||
wire.Locked = true;
|
||||
}
|
||||
}
|
||||
|
||||
//remove all characters except the controlled one to prevent any unintended monster attacks
|
||||
var existingCharacters = Character.CharacterList.FindAll(c => c != Controlled);
|
||||
foreach (Character c in existingCharacters)
|
||||
{
|
||||
c.Remove();
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(4.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "Use WASD to move and the mouse to look around");
|
||||
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
infoBox = CreateInfoFrame("", "Open the door at your right side by highlighting the button next to it with your cursor and pressing E");
|
||||
|
||||
Door tutorialDoor = Item.ItemList.Find(i => i.HasTag("tutorialdoor")).GetComponent<Door>();
|
||||
|
||||
while (!tutorialDoor.IsOpen && Controlled.WorldPosition.X < tutorialDoor.Item.WorldPosition.X)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(2.0f);
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
infoBox = CreateInfoFrame("", "Hold W or S to walk up or down stairs. Use shift to run.", hasButton: true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
//-----------------------------------
|
||||
|
||||
infoBox = CreateInfoFrame("", "At the moment the submarine has no power, which means that crucial systems such as the oxygen generator or the engine aren't running. Let's fix this: go to the upper left corner of the submarine, where you'll find a nuclear reactor.");
|
||||
|
||||
Reactor reactor = Item.ItemList.Find(i => i.HasTag("tutorialreactor")).GetComponent<Reactor>();
|
||||
//reactor.MeltDownTemp = 20000.0f;
|
||||
|
||||
while (Vector2.Distance(Controlled.Position, reactor.Item.Position) > 200.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The reactor requires fuel rods to generate power. You can grab one from the steel cabinet by walking next to it and pressing E.");
|
||||
|
||||
while (Controlled.SelectedConstruction == null || Controlled.SelectedConstruction.Prefab.Identifier != "steelcabinet")
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Pick up one of the fuel rods either by double-clicking or dragging and dropping it into your inventory.");
|
||||
|
||||
while (!HasItem("fuelrod"))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Select the reactor by walking next to it and pressing E.");
|
||||
|
||||
while (Controlled.SelectedConstruction != reactor.Item)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "Load the fuel rod into the reactor by dropping it into any of the 5 slots.");
|
||||
|
||||
while (reactor.AvailableFuel <= 0.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The reactor is now fueled up. Try turning it on by increasing the fission rate.");
|
||||
|
||||
while (reactor.FissionRate <= 0.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "The reactor core has started generating heat, which in turn generates power for the submarine. The power generation is very low at the moment,"
|
||||
+ " because the reactor is set to shut itself down when the temperature rises above 500 degrees Celsius. You can adjust the temperature limit by changing the \"Shutdown Temperature\" in the control panel.", hasButton: true);
|
||||
|
||||
//TODO: reimplement
|
||||
/*while (infoBox != null)
|
||||
{
|
||||
reactor.ShutDownTemp = Math.Min(reactor.ShutDownTemp, 5000.0f);
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("The amount of power generated by the reactor should be kept close to the amount of power consumed by the devices in the submarine. "
|
||||
+ "If there isn't enough power, devices won't function properly (or at all), and if there's too much power, some devices may be damaged."
|
||||
+ " Try to raise the temperature of the reactor close to 3000 degrees by adjusting the fission and cooling rates.", true);
|
||||
|
||||
while (Math.Abs(reactor.Temperature - 3000.0f) > 100.0f)
|
||||
{
|
||||
reactor.AutoTemp = false;
|
||||
reactor.ShutDownTemp = Math.Min(reactor.ShutDownTemp, 5000.0f);
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("Looks like we're up and running! Now you should turn on the \"Automatic temperature control\", which will make the reactor "
|
||||
+ "automatically adjust the temperature to a suitable level. Even though it's an easy way to keep the reactor up and running most of the time, "
|
||||
+ "you should keep in mind that it changes the temperature very slowly and carefully, which may cause issues if there are sudden changes in grid load.");
|
||||
|
||||
while (!reactor.AutoTemp)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}*/
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "That's the basics of operating the reactor! Now that there's power available for the engines, it's time to get the submarine moving. "
|
||||
+ "Deselect the reactor by pressing E and head to the command room at the right edge of the vessel.");
|
||||
|
||||
Steering steering = Item.ItemList.Find(i => i.HasTag("tutorialsteering")).GetComponent<Steering>();
|
||||
Sonar sonar = steering.Item.GetComponent<Sonar>();
|
||||
|
||||
while (Vector2.Distance(Controlled.Position, steering.Item.Position) > 150.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(KeepReactorRunning(reactor));
|
||||
|
||||
infoBox = CreateInfoFrame("", "Select the navigation terminal by walking next to it and pressing E.");
|
||||
|
||||
while (Controlled.SelectedConstruction != steering.Item)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "There seems to be something wrong with the navigation terminal." +
|
||||
" There's nothing on the monitor, so it's probably out of power. The reactor must still be"
|
||||
+ " running or the lights would've gone out, so it's most likely a problem with the wiring."
|
||||
+ " Deselect the terminal by pressing E to start checking the wiring.");
|
||||
|
||||
while (Controlled.SelectedConstruction == steering.Item)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "You need a screwdriver to check the wiring of the terminal."
|
||||
+ " Equip a screwdriver by pulling it to either of the slots with a hand symbol, and then use it on the terminal by left clicking.");
|
||||
|
||||
while (Controlled.SelectedConstruction != steering.Item ||
|
||||
Controlled.HeldItems.FirstOrDefault(i => i.Prefab.Identifier == "screwdriver") == null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
|
||||
infoBox = CreateInfoFrame("", "Here you can see all the wires connected to the terminal. Apparently there's no wire"
|
||||
+ " going into the to the power connection - that's why the monitor isn't working."
|
||||
+ " You should find a piece of wire to connect it. Try searching some of the cabinets scattered around the sub.");
|
||||
|
||||
while (!HasItem("wire"))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Head back to the navigation terminal to fix the wiring.");
|
||||
|
||||
PowerTransfer junctionBox = Item.ItemList.Find(i => i != null && i.HasTag("tutorialjunctionbox")).GetComponent<PowerTransfer>();
|
||||
|
||||
while ((Controlled.SelectedConstruction != junctionBox.Item &&
|
||||
Controlled.SelectedConstruction != steering.Item) ||
|
||||
!Controlled.HeldItems.Any(i => i.Prefab.Identifier == "screwdriver"))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
if (!Controlled.HeldItems.Any(i => i.GetComponent<Wire>() != null))
|
||||
{
|
||||
infoBox = CreateInfoFrame("", "Equip the wire by dragging it to one of the slots with a hand symbol.");
|
||||
|
||||
while (!Controlled.HeldItems.Any(i => i.GetComponent<Wire>() != null))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "You can see the equipped wire at the middle of the connection panel. Drag it to the power connector.");
|
||||
|
||||
var steeringConnection = steering.Item.Connections.Find(c => c.Name.Contains("power"));
|
||||
|
||||
while (steeringConnection.Wires.FirstOrDefault(w => w != null) == null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Now you have to connect the other end of the wire to a power source. "
|
||||
+ "The junction box in the room just below the command room should do.");
|
||||
|
||||
while (Controlled.SelectedConstruction != null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(2.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "You can now move the other end of the wire around, and attach it on the wall by left clicking or "
|
||||
+ "remove the previous attachment by right clicking. Or if you don't care for neatly laid out wiring, you can just "
|
||||
+ "run it straight to the junction box.");
|
||||
|
||||
while (Controlled.SelectedConstruction == null || Controlled.SelectedConstruction.GetComponent<PowerTransfer>() == null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Connect the wire to the junction box by pulling it to the power connection, the same way you did with the navigation terminal.");
|
||||
|
||||
while (sonar.Voltage < 0.1f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Great! Now we should be able to get moving.");
|
||||
|
||||
|
||||
while (Controlled.SelectedConstruction != steering.Item)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "You can take a look at the area around the sub by selecting the \"Active Sonar\" checkbox.");
|
||||
|
||||
while (!sonar.IsActive)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "The blue rectangle in the middle is the submarine, and the flickering shapes outside it are the walls of an underwater cavern. "
|
||||
+ "Try moving the submarine by clicking somewhere on the monitor and dragging the pointer to the direction you want to go to.");
|
||||
|
||||
while (steering.TargetVelocity == Vector2.Zero && steering.TargetVelocity.Length() < 50.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(4.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "The submarine moves up and down by pumping water in and out of the two ballast tanks at the bottom of the submarine. "
|
||||
+ "The engine at the back of the sub moves it forwards and backwards.", hasButton: true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Steer the submarine downwards, heading further into the cavern.");
|
||||
|
||||
while (Submarine.MainSub.WorldPosition.Y > 32000.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
var moloch = Character.Create("moloch", steering.Item.WorldPosition + new Vector2(3000.0f, -500.0f), "");
|
||||
|
||||
moloch.PlaySound(CharacterSound.SoundType.Attack);
|
||||
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "Uh-oh... Something enormous just appeared on the sonar.");
|
||||
|
||||
List<Structure> windows = new List<Structure>();
|
||||
foreach (Structure s in Structure.WallList)
|
||||
{
|
||||
if (s.CastShadow || !s.HasBody) continue;
|
||||
|
||||
if (s.Rect.Right > steering.Item.CurrentHull.Rect.Right) windows.Add(s);
|
||||
}
|
||||
|
||||
float slowdownTimer = 1.0f;
|
||||
bool broken = false;
|
||||
do
|
||||
{
|
||||
steering.TargetVelocity = Vector2.Zero;
|
||||
|
||||
slowdownTimer = Math.Max(0.0f, slowdownTimer - CoroutineManager.DeltaTime * 0.3f);
|
||||
Submarine.MainSub.Velocity *= slowdownTimer;
|
||||
|
||||
moloch.AIController.SelectTarget(steering.Item.CurrentHull.AiTarget);
|
||||
Vector2 steeringDir = windows[0].WorldPosition - moloch.WorldPosition;
|
||||
if (steeringDir != Vector2.Zero) steeringDir = Vector2.Normalize(steeringDir);
|
||||
|
||||
moloch.AIController.SteeringManager.SteeringManual(CoroutineManager.DeltaTime, steeringDir * 100.0f);
|
||||
|
||||
foreach (Structure window in windows)
|
||||
{
|
||||
for (int i = 0; i < window.SectionCount; i++)
|
||||
{
|
||||
if (!window.SectionIsLeaking(i)) continue;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
if (broken) break;
|
||||
}
|
||||
if (broken) break;
|
||||
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
} while (!broken);
|
||||
|
||||
//fix everything except the command windows
|
||||
foreach (Structure w in Structure.WallList)
|
||||
{
|
||||
bool isWindow = windows.Contains(w);
|
||||
|
||||
for (int i = 0; i < w.SectionCount; i++)
|
||||
{
|
||||
if (!w.SectionIsLeaking(i)) continue;
|
||||
|
||||
if (isWindow)
|
||||
{
|
||||
//decrease window damage to slow down the leaking
|
||||
w.AddDamage(i, -w.SectionDamage(i) * 0.48f);
|
||||
}
|
||||
else
|
||||
{
|
||||
w.AddDamage(i, -100000.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Submarine.MainSub.GodMode = true;
|
||||
|
||||
var capacitor1 = Item.ItemList.Find(i => i.HasTag("capacitor1")).GetComponent<PowerContainer>();
|
||||
var capacitor2 = Item.ItemList.Find(i => i.HasTag("capacitor1")).GetComponent<PowerContainer>();
|
||||
CoroutineManager.StartCoroutine(KeepEnemyAway(moloch, new PowerContainer[] { capacitor1, capacitor2 }));
|
||||
|
||||
infoBox = CreateInfoFrame("", "The hull has been breached! Close all the doors to the command room to stop the water from flooding the entire sub!");
|
||||
|
||||
Door commandDoor1 = Item.ItemList.Find(i => i.HasTag("commanddoor1")).GetComponent<Door>();
|
||||
Door commandDoor2 = Item.ItemList.Find(i => i.HasTag("commanddoor2")).GetComponent<Door>();
|
||||
|
||||
//wait until the player is out of the room and the doors are closed
|
||||
while (Controlled.WorldPosition.X > commandDoor1.Item.WorldPosition.X ||
|
||||
(commandDoor1.IsOpen || commandDoor2.IsOpen))
|
||||
{
|
||||
//prevent the hull from filling up completely and crushing the player
|
||||
steering.Item.CurrentHull.WaterVolume = Math.Min(steering.Item.CurrentHull.WaterVolume, steering.Item.CurrentHull.Volume * 0.9f);
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
|
||||
infoBox = CreateInfoFrame("", "You should quickly find yourself a diving mask or a diving suit. " +
|
||||
"There are some in the room next to the airlock.");
|
||||
|
||||
bool divingMaskSelected = false;
|
||||
|
||||
while (!HasItem("divingmask") && !HasItem("divingsuit"))
|
||||
{
|
||||
if (!divingMaskSelected &&
|
||||
Controlled.FocusedItem != null && Controlled.FocusedItem.Prefab.Identifier == "divingsuit")
|
||||
{
|
||||
infoBox = CreateInfoFrame("", "There can only be one item in each inventory slot, so you need to take off "
|
||||
+ "the jumpsuit if you wish to wear a diving suit.");
|
||||
|
||||
divingMaskSelected = true;
|
||||
}
|
||||
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
if (HasItem("divingmask"))
|
||||
{
|
||||
infoBox = CreateInfoFrame("", "The diving mask will let you breathe underwater, but it won't protect from the water pressure outside the sub. " +
|
||||
"It should be fine for the situation at hand, but you still need to find an oxygen tank and drag it into the same slot as the mask." +
|
||||
"You should grab one or two from one of the cabinets.");
|
||||
}
|
||||
else if (HasItem("divingsuit"))
|
||||
{
|
||||
infoBox = CreateInfoFrame("", "In addition to letting you breathe underwater, the suit will protect you from the water pressure outside the sub " +
|
||||
"(unlike the diving mask). However, you still need to drag an oxygen tank into the same slot as the suit to supply oxygen. " +
|
||||
"You should grab one or two from one of the cabinets.");
|
||||
}
|
||||
|
||||
while (!HasItem("oxygentank"))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(5.0f);
|
||||
|
||||
infoBox = CreateInfoFrame("", "Now you should stop the creature attacking the submarine before it does any more damage. Head to the railgun room at the upper right corner of the sub.");
|
||||
|
||||
var railGun = Item.ItemList.Find(i => i.GetComponent<Turret>() != null);
|
||||
|
||||
while (Vector2.Distance(Controlled.Position, railGun.Position) > 500)
|
||||
{
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The railgun requires a large power surge to fire. The reactor can't provide a surge large enough, so we need to use the "
|
||||
+ " supercapacitors in the railgun room. The capacitors need to be charged first; select them and crank up the recharge rate.");
|
||||
|
||||
while (capacitor1.RechargeSpeed < 0.5f && capacitor2.RechargeSpeed < 0.5f)
|
||||
{
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The capacitors take some time to recharge, so now is a good " +
|
||||
"time to head to the room below and load some shells for the railgun.");
|
||||
|
||||
|
||||
var loader = Item.ItemList.Find(i => i.Prefab.Identifier == "railgunloader").GetComponent<ItemContainer>();
|
||||
|
||||
while (Math.Abs(Controlled.Position.Y - loader.Item.Position.Y) > 80)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Grab one of the shells. You can load it by selecting the railgun loader and dragging the shell to. "
|
||||
+ "one of the free slots. You need two hands to carry a shell, so make sure you don't have anything else in either hand.");
|
||||
|
||||
while (loader.Item.ContainedItems.FirstOrDefault(i => i != null && i.Prefab.Identifier == "railgunshell") == null)
|
||||
{
|
||||
//TODO: reimplement
|
||||
//moloch.Health = 50.0f;
|
||||
|
||||
capacitor1.Charge += 5.0f;
|
||||
capacitor2.Charge += 5.0f;
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "Now we're ready to shoot! Select the railgun controller.");
|
||||
|
||||
while (Controlled.SelectedConstruction == null || Controlled.SelectedConstruction.Prefab.Identifier != "railguncontroller")
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
moloch.AnimController.SetPosition(ConvertUnits.ToSimUnits(Controlled.WorldPosition + Vector2.UnitY * 600.0f));
|
||||
|
||||
infoBox = CreateInfoFrame("", "Use the right mouse button to aim and wait for the creature to come closer. When you're ready to shoot, "
|
||||
+ "press the left mouse button.");
|
||||
|
||||
while (!moloch.IsDead)
|
||||
{
|
||||
if (moloch.WorldPosition.Y > Controlled.WorldPosition.Y + 600.0f)
|
||||
{
|
||||
moloch.AIController.SteeringManager.SteeringManual(CoroutineManager.DeltaTime, Controlled.WorldPosition - moloch.WorldPosition);
|
||||
}
|
||||
|
||||
moloch.AIController.SelectTarget(Controlled.AiTarget);
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
Submarine.MainSub.GodMode = false;
|
||||
|
||||
infoBox = CreateInfoFrame("", "The creature has died. Now you should fix the damages in the control room: " +
|
||||
"Grab a welding tool from the closet in the railgun room.");
|
||||
|
||||
while (!HasItem("weldingtool"))
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The welding tool requires fuel to work. Grab a welding fuel tank and attach it to the tool " +
|
||||
"by dragging it into the same slot.");
|
||||
|
||||
do
|
||||
{
|
||||
var weldingTool = Controlled.Inventory.FindItemByIdentifier("weldingtool");
|
||||
if (weldingTool != null &&
|
||||
weldingTool.ContainedItems.FirstOrDefault(contained => contained != null && contained.Prefab.Identifier == "weldingfueltank") != null) break;
|
||||
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
} while (true);
|
||||
|
||||
|
||||
infoBox = CreateInfoFrame("", "You can aim with the tool using the right mouse button and weld using the left button. " +
|
||||
"Head to the command room to fix the leaks there.");
|
||||
|
||||
do
|
||||
{
|
||||
broken = false;
|
||||
foreach (Structure window in windows)
|
||||
{
|
||||
for (int i = 0; i < window.SectionCount; i++)
|
||||
{
|
||||
if (!window.SectionIsLeaking(i)) continue;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
if (broken) break;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
} while (broken);
|
||||
|
||||
infoBox = CreateInfoFrame("", "The hull is fixed now, but there's still quite a bit of water inside the sub. It should be pumped out "
|
||||
+ "using the bilge pump in the room at the bottom of the submarine.");
|
||||
|
||||
Pump pump = Item.ItemList.Find(i => i.HasTag("tutorialpump")).GetComponent<Pump>();
|
||||
|
||||
while (Vector2.Distance(Controlled.Position, pump.Item.Position) > 100.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The two pumps inside the ballast tanks "
|
||||
+ "are connected straight to the navigation terminal and can't be manually controlled unless you mess with their wiring, " +
|
||||
"so you should only use the pump in the middle room to pump out the water. Select it, turn it on and adjust the pumping speed " +
|
||||
"to start pumping water out.", hasButton: true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
|
||||
bool brokenMsgShown = false;
|
||||
|
||||
Item brokenBox = null;
|
||||
|
||||
while (pump.FlowPercentage > 0.0f || pump.CurrFlow <= 0.0f || !pump.IsActive)
|
||||
{
|
||||
if (!brokenMsgShown && pump.Voltage < pump.MinVoltage && Controlled.SelectedConstruction == pump.Item)
|
||||
{
|
||||
brokenMsgShown = true;
|
||||
|
||||
infoBox = CreateInfoFrame("", "Looks like the pump isn't getting any power. The water must have short-circuited some of the junction "
|
||||
+ "boxes. You can check which boxes are broken by selecting them.");
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (Controlled.SelectedConstruction!=null &&
|
||||
Controlled.SelectedConstruction.GetComponent<PowerTransfer>() != null &&
|
||||
Controlled.SelectedConstruction.Condition == 0.0f)
|
||||
{
|
||||
brokenBox = Controlled.SelectedConstruction;
|
||||
|
||||
infoBox = CreateInfoFrame("", "Here's our problem: this junction box is broken. Luckily engineers are adept at fixing electrical devices - "
|
||||
+ "you just need to find a spare wire and click the \"Fix\"-button to repair the box.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (pump.Voltage > pump.MinVoltage) break;
|
||||
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
}
|
||||
|
||||
if (brokenBox != null && brokenBox.ConditionPercentage > 50.0f && pump.Voltage < pump.MinVoltage)
|
||||
{
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
|
||||
if (pump.Voltage < pump.MinVoltage)
|
||||
{
|
||||
infoBox = CreateInfoFrame("", "The pump is still not running. Check if there are more broken junction boxes between the pump and the reactor.");
|
||||
}
|
||||
brokenBox = null;
|
||||
}
|
||||
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "The pump is up and running. Wait for the water to be drained out.");
|
||||
|
||||
while (pump.Item.CurrentHull.WaterVolume > 1000.0f)
|
||||
{
|
||||
yield return Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("", "That was all there is to this tutorial! Now you should be able to handle " +
|
||||
"most of the basic tasks on board the submarine.");
|
||||
|
||||
Completed = true;
|
||||
|
||||
yield return new WaitForSeconds(4.0f);
|
||||
|
||||
Controlled = null;
|
||||
GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||
GameMain.LightManager.LosEnabled = false;
|
||||
|
||||
var cinematic = new CameraTransition(Submarine.MainSub, GameMain.GameScreen.Cam, Alignment.CenterLeft, Alignment.CenterRight, panDuration: 5.0f);
|
||||
|
||||
while (cinematic.Running)
|
||||
{
|
||||
yield return Controlled != null && Controlled.IsDead ? CoroutineStatus.Success : CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
Submarine.Unload();
|
||||
GameMain.MainMenuScreen.Select();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private bool HasItem(string itemIdentifier)
|
||||
{
|
||||
if (Character.Controlled == null) return false;
|
||||
|
||||
return Character.Controlled.Inventory.FindItemByIdentifier(itemIdentifier) != null;
|
||||
}
|
||||
|
||||
protected IEnumerable<CoroutineStatus> KeepReactorRunning(Reactor reactor)
|
||||
{
|
||||
do
|
||||
{
|
||||
//TODO: reimplement
|
||||
/*reactor.AutoTemp = true;
|
||||
reactor.ShutDownTemp = 5000.0f;*/
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (Item.ItemList.Contains(reactor.Item));
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// keeps the enemy away from the sub until the capacitors are loaded
|
||||
/// </summary>
|
||||
private IEnumerable<CoroutineStatus> KeepEnemyAway(Character enemy, PowerContainer[] capacitors)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (enemy == null || Character.Controlled == null) break;
|
||||
|
||||
//TODO: reimplement
|
||||
//enemy.Health = 50.0f;
|
||||
|
||||
if (enemy.AIController is EnemyAIController enemyAI)
|
||||
{
|
||||
enemyAI.State = AIState.Idle;
|
||||
}
|
||||
|
||||
Vector2 targetPos = Character.Controlled.WorldPosition + new Vector2(0.0f, 3000.0f);
|
||||
|
||||
Vector2 steering = targetPos - enemy.WorldPosition;
|
||||
if (steering != Vector2.Zero) steering = Vector2.Normalize(steering);
|
||||
|
||||
enemy.AIController.Steering = steering;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (capacitors.FirstOrDefault(c => c.Charge > 0.4f) == null);
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+77
-28
@@ -41,30 +41,79 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
// Variables
|
||||
private Character captain;
|
||||
private string radioSpeakerName;
|
||||
private LocalizedString radioSpeakerName;
|
||||
private Sprite captain_steerIcon;
|
||||
private Color captain_steerIconColor;
|
||||
|
||||
public CaptainTutorial(XElement element) : base(element)
|
||||
public CaptainTutorial() : base("tutorial.captaintraining".ToIdentifier(),
|
||||
new Segment(
|
||||
"Captain.CommandMedic".ToIdentifier(),
|
||||
"Captain.CommandMedicObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Captain.CommandMedicText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_command.webm", TextTag = "Captain.CommandMedicText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Captain.CommandMechanic".ToIdentifier(),
|
||||
"Captain.CommandMechanicObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Captain.CommandMechanicText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Captain.CommandSecurity".ToIdentifier(),
|
||||
"Captain.CommandSecurityObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Captain.CommandSecurityText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Captain.CommandEngineer".ToIdentifier(),
|
||||
"Captain.CommandEngineerObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Captain.CommandEngineerText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Captain.Undock".ToIdentifier(),
|
||||
"Captain.UndockObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Captain.UndockText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_undock.webm", TextTag = "Captain.UndockText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Captain.Navigate".ToIdentifier(),
|
||||
"Captain.NavigateObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Captain.NavigateText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_navigation.webm", TextTag = "Captain.NavigateText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Captain.Dock".ToIdentifier(),
|
||||
"Captain.DockObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Captain.DockText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_docking.webm", TextTag = "Captain.DockText".ToIdentifier(), Width = 450, Height = 80 }))
|
||||
{ }
|
||||
|
||||
protected override CharacterInfo GetCharacterInfo()
|
||||
{
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["captain"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 20),
|
||||
new Skill("weapons".ToIdentifier(), 20),
|
||||
new Skill("mechanical".ToIdentifier(), 20),
|
||||
new Skill("electrical".ToIdentifier(), 20),
|
||||
new Skill("helm".ToIdentifier(), 70)));
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
captain = Character.Controlled;
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Watchman");
|
||||
GameMain.GameSession.CrewManager.AllowCharacterSwitch = false;
|
||||
|
||||
var revolver = FindOrGiveItem(captain, "revolver");
|
||||
var revolver = FindOrGiveItem(captain, "revolver".ToIdentifier());
|
||||
revolver.Unequip(captain);
|
||||
captain.Inventory.RemoveItem(revolver);
|
||||
|
||||
var captainscap =
|
||||
captain.Inventory.FindItemByIdentifier("captainscap1") ??
|
||||
captain.Inventory.FindItemByIdentifier("captainscap2") ??
|
||||
captain.Inventory.FindItemByIdentifier("captainscap3");
|
||||
captain.Inventory.FindItemByIdentifier("captainscap1".ToIdentifier()) ??
|
||||
captain.Inventory.FindItemByIdentifier("captainscap2".ToIdentifier()) ??
|
||||
captain.Inventory.FindItemByIdentifier("captainscap3".ToIdentifier());
|
||||
|
||||
if (captainscap != null)
|
||||
{
|
||||
@@ -73,16 +122,16 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
|
||||
var captainsuniform =
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform1") ??
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform2") ??
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform3");
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform1".ToIdentifier()) ??
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform2".ToIdentifier()) ??
|
||||
captain.Inventory.FindItemByIdentifier("captainsuniform3".ToIdentifier());
|
||||
if (captainsuniform != null)
|
||||
{
|
||||
captainsuniform.Unequip(captain);
|
||||
captain.Inventory.RemoveItem(captainsuniform);
|
||||
}
|
||||
|
||||
var steerOrder = Order.GetPrefab("steer");
|
||||
var steerOrder = OrderPrefab.Prefabs["steer"];
|
||||
captain_steerIcon = steerOrder.SymbolSprite;
|
||||
captain_steerIconColor = steerOrder.Color;
|
||||
|
||||
@@ -99,7 +148,7 @@ namespace Barotrauma.Tutorials
|
||||
captain_medicSpawnPos = Item.ItemList.Find(i => i.HasTag("captain_medicspawnpos")).WorldPosition;
|
||||
tutorial_submarineDoor = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoor")).GetComponent<Door>();
|
||||
tutorial_submarineDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_submarinedoorlight")).GetComponent<LightComponent>();
|
||||
var medicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("medicaldoctor"));
|
||||
var medicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("medicaldoctor"));
|
||||
captain_medic = Character.Create(medicInfo, captain_medicSpawnPos, "medicaldoctor");
|
||||
captain_medic.TeamID = CharacterTeamType.Team1;
|
||||
captain_medic.GiveJobItems(null);
|
||||
@@ -122,17 +171,17 @@ namespace Barotrauma.Tutorials
|
||||
SetDoorAccess(tutorial_lockedDoor_1, null, false);
|
||||
SetDoorAccess(tutorial_lockedDoor_2, null, false);
|
||||
|
||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("mechanic"));
|
||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("mechanic"));
|
||||
captain_mechanic = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "mechanic");
|
||||
captain_mechanic.TeamID = CharacterTeamType.Team1;
|
||||
captain_mechanic.GiveJobItems();
|
||||
|
||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("securityofficer"));
|
||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("securityofficer"));
|
||||
captain_security = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "securityofficer");
|
||||
captain_security.TeamID = CharacterTeamType.Team1;
|
||||
captain_security.GiveJobItems();
|
||||
|
||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer"));
|
||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer"));
|
||||
captain_engineer = Character.Create(engineerInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "engineer");
|
||||
captain_engineer.TeamID = CharacterTeamType.Team1;
|
||||
captain_engineer.GiveJobItems();
|
||||
@@ -163,7 +212,7 @@ namespace Barotrauma.Tutorials
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
GameMain.GameSession.CrewManager.AutoShowCrewList();
|
||||
GameMain.GameSession.CrewManager.AddCharacter(captain_medic);
|
||||
TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Command));
|
||||
TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command));
|
||||
do
|
||||
{
|
||||
yield return null;
|
||||
@@ -172,13 +221,13 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
while (!HasOrder(captain_medic, "follow"));
|
||||
SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, true);
|
||||
RemoveCompletedObjective(segments[0]);
|
||||
RemoveCompletedObjective(0);
|
||||
|
||||
// Submarine
|
||||
do { yield return null; } while (!captain_enteredSubmarineSensor.MotionDetected);
|
||||
yield return new WaitForSeconds(3f, false);
|
||||
captain_mechanic.AIController.Enabled = captain_security.AIController.Enabled = captain_engineer.AIController.Enabled = true;
|
||||
TriggerTutorialSegment(1, GameMain.Config.KeyBindText(InputType.Command));
|
||||
TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command));
|
||||
GameMain.GameSession.CrewManager.AddCharacter(captain_mechanic);
|
||||
do
|
||||
{
|
||||
@@ -187,9 +236,9 @@ namespace Barotrauma.Tutorials
|
||||
// GameMain.GameSession.CrewManager.HighlightOrderButton(captain_mechanic, "repairsystems", highlightColor, new Vector2(5, 5));
|
||||
//HighlightOrderOption("jobspecific");
|
||||
} while (!HasOrder(captain_mechanic, "repairsystems") && !HasOrder(captain_mechanic, "repairmechanical") && !HasOrder(captain_mechanic, "repairelectrical"));
|
||||
RemoveCompletedObjective(segments[1]);
|
||||
RemoveCompletedObjective(1);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
TriggerTutorialSegment(2, GameMain.Config.KeyBindText(InputType.Command));
|
||||
TriggerTutorialSegment(2, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command));
|
||||
GameMain.GameSession.CrewManager.AddCharacter(captain_security);
|
||||
do
|
||||
{
|
||||
@@ -199,9 +248,9 @@ namespace Barotrauma.Tutorials
|
||||
HighlightOrderOption("fireatwill");
|
||||
}
|
||||
while (!HasOrder(captain_security, "operateweapons"));
|
||||
RemoveCompletedObjective(segments[2]);
|
||||
RemoveCompletedObjective(2);
|
||||
yield return new WaitForSeconds(4f, false);
|
||||
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Command));
|
||||
TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command));
|
||||
GameMain.GameSession.CrewManager.AddCharacter(captain_engineer);
|
||||
do
|
||||
{
|
||||
@@ -211,7 +260,7 @@ namespace Barotrauma.Tutorials
|
||||
HighlightOrderOption("powerup");
|
||||
}
|
||||
while (!HasOrder(captain_engineer, "operatereactor", "powerup"));
|
||||
RemoveCompletedObjective(segments[3]);
|
||||
RemoveCompletedObjective(3);
|
||||
tutorial_submarineReactor.CanBeSelected = true;
|
||||
do { yield return null; } while (!tutorial_submarineReactor.IsActive); // Wait until reactor on
|
||||
TriggerTutorialSegment(4);
|
||||
@@ -226,7 +275,7 @@ namespace Barotrauma.Tutorials
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
} while (Submarine.MainSub.DockedTo.Any());
|
||||
captain_navConsole.UseAutoDocking = false;
|
||||
RemoveCompletedObjective(segments[4]);
|
||||
RemoveCompletedObjective(4);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
TriggerTutorialSegment(5); // Navigate to destination
|
||||
do
|
||||
@@ -241,7 +290,7 @@ namespace Barotrauma.Tutorials
|
||||
yield return null;
|
||||
} while (captain_sonar.CurrentMode != Sonar.Mode.Active);
|
||||
do { yield return null; } while (Vector2.Distance(Submarine.MainSub.WorldPosition, Level.Loaded.EndPosition) > 4000f);
|
||||
RemoveCompletedObjective(segments[5]);
|
||||
RemoveCompletedObjective(5);
|
||||
captain_navConsole.UseAutoDocking = true;
|
||||
yield return new WaitForSeconds(4f, false);
|
||||
TriggerTutorialSegment(6); // Docking
|
||||
@@ -250,7 +299,7 @@ namespace Barotrauma.Tutorials
|
||||
//captain_navConsoleCustomInterface.HighlightElement(0, uiHighlightColor, duration: 1.0f, pulsateAmount: 0.0f);
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
} while (!Submarine.MainSub.AtEndExit || !Submarine.MainSub.DockedTo.Any());
|
||||
RemoveCompletedObjective(segments[6]);
|
||||
RemoveCompletedObjective(6);
|
||||
yield return new WaitForSeconds(3f, false);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.GetWithVariable("Captain.Radio.Complete", "[OUTPOSTNAME]", GameMain.GameSession.EndLocation.Name), ChatMessageType.Radio, null);
|
||||
SetHighlight(captain_navConsole.Item, false);
|
||||
|
||||
-520
@@ -1,520 +0,0 @@
|
||||
/*using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
using System;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Items.Components;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
class ContextualTutorial : Tutorial
|
||||
{
|
||||
public ContextualTutorial(XElement element) : base(element)
|
||||
{
|
||||
//Name = "ContextualTutorial";
|
||||
}
|
||||
|
||||
public static bool Selected = false;
|
||||
|
||||
private Steering navConsole;
|
||||
private Reactor reactor;
|
||||
private Sonar sonar;
|
||||
private Vector2 subStartingPosition;
|
||||
private List<Character> crew;
|
||||
private Character mechanic;
|
||||
private Character engineer;
|
||||
private Character injuredMember = null;
|
||||
|
||||
private List<Pair<Character, float>> characterTimeOnSonar;
|
||||
private float requiredTimeOnSonar = 5f;
|
||||
|
||||
private float tutorialTimer;
|
||||
|
||||
private bool disableTutorialOnDeficiencyFound = true;
|
||||
|
||||
private float floodTutorialTimer = 0.0f;
|
||||
private const float floodTutorialDelay = 2.0f;
|
||||
private float medicalTutorialTimer = 0.0f;
|
||||
private const float medicalTutorialDelay = 2.0f;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
for (int i = 0; i < segments.Count; i++)
|
||||
{
|
||||
segments[i].IsTriggered = false;
|
||||
}
|
||||
|
||||
characterTimeOnSonar = new List<Pair<Character, float>>();
|
||||
}
|
||||
|
||||
public void LoadPartiallyComplete(XElement element)
|
||||
{
|
||||
int[] completedSegments = element.GetAttributeIntArray("completedsegments", null);
|
||||
|
||||
if (completedSegments == null || completedSegments.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (completedSegments.Length == segments.Count) // Completed all segments
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < completedSegments.Length; i++)
|
||||
{
|
||||
segments[completedSegments[i]].IsTriggered = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void SavePartiallyComplete(XElement element)
|
||||
{
|
||||
XElement tutorialElement = new XElement("contextualtutorial");
|
||||
tutorialElement.Add(new XAttribute("completedsegments", GetCompletedSegments()));
|
||||
element.Add(tutorialElement);
|
||||
}
|
||||
|
||||
private string GetCompletedSegments()
|
||||
{
|
||||
string completedSegments = string.Empty;
|
||||
|
||||
for (int i = 0; i < segments.Count; i++)
|
||||
{
|
||||
if (segments[i].IsTriggered)
|
||||
{
|
||||
completedSegments += i + ",";
|
||||
}
|
||||
}
|
||||
|
||||
if (completedSegments.Length > 0)
|
||||
{
|
||||
completedSegments = completedSegments.TrimEnd(',');
|
||||
}
|
||||
|
||||
return completedSegments;
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
if (!Initialized) return;
|
||||
|
||||
base.Start();
|
||||
injuredMember = null;
|
||||
activeContentSegment = null;
|
||||
tutorialTimer = floodTutorialTimer = medicalTutorialTimer = 0.0f;
|
||||
subStartingPosition = Vector2.Zero;
|
||||
characterTimeOnSonar.Clear();
|
||||
|
||||
subStartingPosition = Submarine.MainSub.WorldPosition;
|
||||
navConsole = Item.ItemList.Find(i => i.HasTag("command"))?.GetComponent<Steering>();
|
||||
sonar = navConsole?.Item.GetComponent<Sonar>();
|
||||
reactor = Item.ItemList.Find(i => i.HasTag("reactor"))?.GetComponent<Reactor>();
|
||||
|
||||
#if DEBUG
|
||||
if (reactor == null || navConsole == null || sonar == null)
|
||||
{
|
||||
infoBox = CreateInfoFrame("Error", "Submarine not compatible with the tutorial:"
|
||||
+ "\nReactor - " + (reactor != null ? "OK" : "Tag 'reactor' not found")
|
||||
+ "\nNavigation Console - " + (navConsole != null ? "OK" : "Tag 'command' not found")
|
||||
+ "\nSonar - " + (sonar != null ? "OK" : "Not found under Navigation Console"), hasButton: true);
|
||||
CoroutineManager.StartCoroutine(WaitForErrorClosed());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (disableTutorialOnDeficiencyFound)
|
||||
{
|
||||
if (reactor == null || navConsole == null || sonar == null)
|
||||
{
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (navConsole == null) segments[2].IsTriggered = true; // Disable navigation console usage tutorial
|
||||
if (reactor == null) segments[5].IsTriggered = true; // Disable reactor usage tutorial
|
||||
if (sonar == null) segments[6].IsTriggered = true; // Disable enemy on sonar tutorial
|
||||
}
|
||||
|
||||
crew = GameMain.GameSession.CrewManager.GetCharacters().ToList();
|
||||
mechanic = CrewMemberWithJob("mechanic");
|
||||
engineer = CrewMemberWithJob("engineer");
|
||||
|
||||
Completed = true; // Trigger completed at start to prevent the contextual tutorial from automatically activating on starting new campaigns after this one
|
||||
started = true;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
private IEnumerable<object> WaitForErrorClosed()
|
||||
{
|
||||
while (infoBox != null) yield return null;
|
||||
Stop();
|
||||
}
|
||||
#endif
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
base.Stop();
|
||||
characterTimeOnSonar = null;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
|
||||
if (!started || ContentRunning) return;
|
||||
|
||||
deltaTime *= 0.5f;
|
||||
|
||||
for (int i = 0; i < segments.Count; i++)
|
||||
{
|
||||
if (segments[i].IsTriggered || HasObjective(segments[i])) continue;
|
||||
if (CheckContextualTutorials(i, deltaTime)) // Found a relevant tutorial, halt finding new ones
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckContextualTutorials(int index, float deltaTime)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: // Welcome: Game Start [Text]
|
||||
if (tutorialTimer < 1.0f)
|
||||
{
|
||||
tutorialTimer += deltaTime;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 1: // Command Reactor: 2 seconds after 'Welcome' dismissed and only if no command given to start reactor [Video]
|
||||
if (!segments[0].IsTriggered) return false;
|
||||
if (tutorialTimer < 3.0f)
|
||||
{
|
||||
tutorialTimer += deltaTime;
|
||||
|
||||
if (HasOrder("operatereactor"))
|
||||
{
|
||||
segments[index].IsTriggered = true;
|
||||
tutorialTimer = 2.5f;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 2: // Nav Console: 2 seconds after 'Command Reactor' dismissed or if nav console is activated [Video]
|
||||
if (!IsReactorPoweredUp()) return false; // Do not advance tutorial based on this segment if reactor has not been powered up
|
||||
if (Character.Controlled?.SelectedConstruction != navConsole.Item)
|
||||
{
|
||||
if (tutorialTimer < 4.5f)
|
||||
{
|
||||
tutorialTimer += deltaTime;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tutorialTimer = 4.5f;
|
||||
}
|
||||
|
||||
TriggerTutorialSegment(index, GameMain.GameSession.EndLocation.Name);
|
||||
return true;
|
||||
case 3: // Objective: Travel ~150 meters and while sub is not flooding [Text]
|
||||
if (Vector2.Distance(subStartingPosition, Submarine.MainSub.WorldPosition) < 8000f || IsFlooding())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else // Called earlier than others due to requiring specific args
|
||||
{
|
||||
TriggerTutorialSegment(index, GameMain.GameSession.EndLocation.Name);
|
||||
return true;
|
||||
}
|
||||
case 4: // Flood: Hull is breached and sub is taking on water [Video]
|
||||
if (!IsFlooding())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (floodTutorialTimer < floodTutorialDelay)
|
||||
{
|
||||
floodTutorialTimer += deltaTime;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 5: // Reactor: Player uses reactor for the first time [Video]
|
||||
if (Character.Controlled?.SelectedConstruction != reactor.Item)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 6: // Enemy on Sonar: Player witnesses creature signal on sonar for 5 seconds [Video]
|
||||
if (!HasEnemyOnSonarForDuration(deltaTime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 7: // Degrading1: Any equipment degrades to 50% health or less and player has not assigned any crew to perform maintenance [Text]
|
||||
if ((mechanic == null || mechanic.IsDead) && (engineer == null || engineer.IsDead)) // Both engineer and mechanic are dead or do not exist -> do not display
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool degradedEquipmentFound = false;
|
||||
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (!item.Repairables.Any() || item.Condition > 50.0f) continue;
|
||||
degradedEquipmentFound = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (degradedEquipmentFound)
|
||||
{
|
||||
if (HasOrder("repairsystems", "jobspecific"))
|
||||
{
|
||||
segments[index].IsTriggered = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 8: // Medical: Crewmember is injured but not killed [Video]
|
||||
|
||||
if (injuredMember == null)
|
||||
{
|
||||
for (int i = 0; i < crew.Count; i++)
|
||||
{
|
||||
Character member = crew[i];
|
||||
if (member.Vitality < member.MaxVitality && !member.IsDead)
|
||||
{
|
||||
injuredMember = member;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (medicalTutorialTimer < medicalTutorialDelay)
|
||||
{
|
||||
medicalTutorialTimer += deltaTime;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
TriggerTutorialSegment(index, new string[] { injuredMember.Info.DisplayName,
|
||||
(injuredMember.Info.Gender == Gender.Male) ? TextManager.Get("PronounPossessiveMale").ToLower() : TextManager.Get("PronounPossessiveFemale").ToLower() });
|
||||
return true;
|
||||
}
|
||||
case 9: // Approach1: Destination is within ~100m [Video]
|
||||
if (Vector2.Distance(Submarine.MainSub.WorldPosition, Level.Loaded.EndPosition) > 8000f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
TriggerTutorialSegment(index, GameMain.GameSession.EndLocation.Name);
|
||||
return true;
|
||||
}
|
||||
case 10: // Approach2: Sub is docked [Text]
|
||||
if (!Submarine.MainSub.AtEndPosition || Submarine.MainSub.DockedTo.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
TriggerTutorialSegment(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void CheckActiveObjectives(TutorialSegment objective, float deltaTime)
|
||||
{
|
||||
switch(objective.Id)
|
||||
{
|
||||
case "ReactorCommand": // Reactor commanded
|
||||
if (!IsReactorPoweredUp())
|
||||
{
|
||||
if (!HasOrder("operatereactor")) return;
|
||||
}
|
||||
break;
|
||||
case "NavConsole": // traveled 50 meters
|
||||
if (Vector2.Distance(subStartingPosition, Submarine.MainSub.WorldPosition) < 4000f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "Flood": // Hull breaches repaired
|
||||
if (IsFlooding()) return;
|
||||
break;
|
||||
case "Medical":
|
||||
if (injuredMember != null && !injuredMember.IsDead)
|
||||
{
|
||||
if (injuredMember.CharacterHealth.DroppedItem == null) return;
|
||||
}
|
||||
break;
|
||||
case "EnemyOnSonar": // Enemy dispatched
|
||||
if (HasEnemyOnSonarForDuration(deltaTime))
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "Degrading": // Fixed
|
||||
if (mechanic != null && !mechanic.IsDead)
|
||||
{
|
||||
HumanAIController humanAI = mechanic.AIController as HumanAIController;
|
||||
if (mechanic.CurrentOrder?.AITag != "repairsystems" || humanAI.CurrentOrderOption != "jobspecific")
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (engineer != null && !engineer.IsDead)
|
||||
{
|
||||
HumanAIController humanAI = engineer.AIController as HumanAIController;
|
||||
if (engineer.CurrentOrder?.AITag != "repairsystems" || humanAI.CurrentOrderOption != "jobspecific")
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case "Approach1": // Wait until docked
|
||||
if (!Submarine.MainSub.AtEndPosition || Submarine.MainSub.DockedTo.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
RemoveCompletedObjective(objective);
|
||||
}
|
||||
|
||||
private bool IsReactorPoweredUp()
|
||||
{
|
||||
float load = 0.0f;
|
||||
List<Connection> connections = reactor.Item.Connections;
|
||||
if (connections != null && connections.Count > 0)
|
||||
{
|
||||
foreach (Connection connection in connections)
|
||||
{
|
||||
if (!connection.IsPower) continue;
|
||||
foreach (Connection recipient in connection.Recipients)
|
||||
{
|
||||
if (!(recipient.Item is Item it)) continue;
|
||||
|
||||
PowerTransfer pt = it.GetComponent<PowerTransfer>();
|
||||
if (pt == null) continue;
|
||||
|
||||
load = Math.Max(load, pt.PowerLoad);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Math.Abs(load + reactor.CurrPowerConsumption) < 10;
|
||||
}
|
||||
|
||||
private Character CrewMemberWithJob(string job)
|
||||
{
|
||||
job = job.ToLowerInvariant();
|
||||
for (int i = 0; i < crew.Count; i++)
|
||||
{
|
||||
if (crew[i].Info.Job.Prefab.Identifier.ToLowerInvariant() == job) return crew[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool HasOrder(string aiTag, string option = null)
|
||||
{
|
||||
for (int i = 0; i < crew.Count; i++)
|
||||
{
|
||||
if (crew[i].CurrentOrder?.AITag == aiTag)
|
||||
{
|
||||
if (option == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
HumanAIController humanAI = crew[i].AIController as HumanAIController;
|
||||
return humanAI.CurrentOrderOption == option;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsFlooding()
|
||||
{
|
||||
foreach (Gap gap in Gap.GapList)
|
||||
{
|
||||
if (gap.ConnectedWall == null || gap.IsRoomToRoom) continue;
|
||||
if (gap.ConnectedDoor != null || gap.Open <= 0.0f) continue;
|
||||
if (gap.Submarine == null) continue;
|
||||
if (gap.Submarine.IsOutpost) continue;
|
||||
if (gap.Submarine != Submarine.MainSub) continue;
|
||||
if (gap.FlowTargetHull == null || gap.FlowTargetHull.WaterPercentage <= 0.0f) continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool HasEnemyOnSonarForDuration(float deltaTime)
|
||||
{
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.AnimController.CurrentHull != null || !c.Enabled || !(c.AIController is EnemyAIController)) continue;
|
||||
if (sonar.DetectSubmarineWalls && c.AnimController.CurrentHull == null && sonar.Item.CurrentHull != null) continue;
|
||||
if (Vector2.DistanceSquared(c.WorldPosition, sonar.Item.WorldPosition) > sonar.Range * sonar.Range)
|
||||
{
|
||||
for (int i = 0; i < characterTimeOnSonar.Count; i++)
|
||||
{
|
||||
if (characterTimeOnSonar[i].First == c)
|
||||
{
|
||||
characterTimeOnSonar.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Pair<Character, float> pair = characterTimeOnSonar.Find(ct => ct.First == c);
|
||||
if (pair != null)
|
||||
{
|
||||
pair.Second += deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
characterTimeOnSonar.Add(new Pair<Character, float>(c, deltaTime));
|
||||
}
|
||||
}
|
||||
|
||||
return characterTimeOnSonar.Find(ct => ct.Second >= requiredTimeOnSonar && !ct.First.IsDead) != null;
|
||||
}
|
||||
|
||||
protected override void TriggerTutorialSegment(int index, params object[] args)
|
||||
{
|
||||
base.TriggerTutorialSegment(index, args);
|
||||
|
||||
for (int i = 0; i < segments.Count; i++)
|
||||
{
|
||||
if (!segments[i].IsTriggered) return;
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(WaitToStop()); // Completed
|
||||
}
|
||||
|
||||
private IEnumerable<object> WaitToStop()
|
||||
{
|
||||
while (ContentRunning) yield return null;
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
}*/
|
||||
+93
-41
@@ -15,7 +15,7 @@ namespace Barotrauma.Tutorials
|
||||
private float shakeTimer = 1f;
|
||||
private float shakeAmount = 20f;
|
||||
|
||||
private string radioSpeakerName;
|
||||
private LocalizedString radioSpeakerName;
|
||||
private Character doctor;
|
||||
|
||||
private ItemContainer doctor_suppliesCabinet;
|
||||
@@ -40,14 +40,66 @@ namespace Barotrauma.Tutorials
|
||||
private Sprite doctor_firstAidIcon;
|
||||
private Color doctor_firstAidIconColor;
|
||||
|
||||
public DoctorTutorial(XElement element) : base(element)
|
||||
{
|
||||
}
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
var firstAidOrder = Order.GetPrefab("requestfirstaid");
|
||||
public DoctorTutorial() : base("tutorial.medicaldoctortraining".ToIdentifier(),
|
||||
new Segment(
|
||||
"Doctor.Supplies".ToIdentifier(),
|
||||
"Doctor.SuppliesObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Doctor.SuppliesText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Doctor.OpenMedicalInterface".ToIdentifier(),
|
||||
"Doctor.OpenMedicalInterfaceObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Doctor.OpenMedicalInterfaceText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_medinterface1.webm", TextTag = "Doctor.OpenMedicalInterfaceText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Doctor.FirstAidSelf".ToIdentifier(),
|
||||
"Doctor.FirstAidSelfObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Doctor.FirstAidSelfText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_medinterface1.webm", TextTag = "Doctor.FirstAidSelfText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Doctor.Medbay".ToIdentifier(),
|
||||
"Doctor.MedbayObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Doctor.MedbayText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_command.webm", TextTag = "Doctor.MedbayText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Doctor.TreatBurns".ToIdentifier(),
|
||||
"Doctor.TreatBurnsObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Doctor.TreatBurnsText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_medinterface2.webm", TextTag = "Doctor.TreatBurnsText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Doctor.CPR".ToIdentifier(),
|
||||
"Doctor.CPRObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Doctor.CPRText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_cpr.webm", TextTag = "Doctor.CPRText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Doctor.Submarine".ToIdentifier(),
|
||||
"Doctor.SubmarineObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Doctor.SubmarineText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }))
|
||||
{ }
|
||||
|
||||
protected override CharacterInfo GetCharacterInfo()
|
||||
{
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 70),
|
||||
new Skill("weapons".ToIdentifier(), 20),
|
||||
new Skill("mechanical".ToIdentifier(), 20),
|
||||
new Skill("electrical".ToIdentifier(), 20),
|
||||
new Skill("helm".ToIdentifier(), 20)));
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
var firstAidOrder = OrderPrefab.Prefabs["requestfirstaid"];
|
||||
doctor_firstAidIcon = firstAidOrder.SymbolSprite;
|
||||
doctor_firstAidIconColor = firstAidOrder.Color;
|
||||
|
||||
@@ -55,19 +107,19 @@ namespace Barotrauma.Tutorials
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker");
|
||||
doctor = Character.Controlled;
|
||||
|
||||
var bandages = FindOrGiveItem(doctor, "antibleeding1");
|
||||
var bandages = FindOrGiveItem(doctor, "antibleeding1".ToIdentifier());
|
||||
bandages.Unequip(doctor);
|
||||
doctor.Inventory.RemoveItem(bandages);
|
||||
|
||||
var syringegun = FindOrGiveItem(doctor, "syringegun");
|
||||
var syringegun = FindOrGiveItem(doctor, "syringegun".ToIdentifier());
|
||||
syringegun.Unequip(doctor);
|
||||
doctor.Inventory.RemoveItem(syringegun);
|
||||
|
||||
var antibiotics = FindOrGiveItem(doctor, "antibiotics");
|
||||
var antibiotics = FindOrGiveItem(doctor, "antibiotics".ToIdentifier());
|
||||
antibiotics.Unequip(doctor);
|
||||
doctor.Inventory.RemoveItem(antibiotics);
|
||||
|
||||
var morphine = FindOrGiveItem(doctor, "antidama1");
|
||||
var morphine = FindOrGiveItem(doctor, "antidama1".ToIdentifier());
|
||||
morphine.Unequip(doctor);
|
||||
doctor.Inventory.RemoveItem(morphine);
|
||||
|
||||
@@ -78,7 +130,7 @@ namespace Barotrauma.Tutorials
|
||||
var patientHull2 = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "airlock").CurrentHull;
|
||||
medBay = WayPoint.WayPointList.Find(wp => wp.IdCardDesc == "medbay").CurrentHull;
|
||||
|
||||
var assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("assistant"));
|
||||
var assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("assistant"));
|
||||
patient1 = Character.Create(assistantInfo, patientHull1.WorldPosition, "1");
|
||||
patient1.TeamID = CharacterTeamType.Team1;
|
||||
patient1.GiveJobItems(null);
|
||||
@@ -86,26 +138,26 @@ namespace Barotrauma.Tutorials
|
||||
patient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 15.0f) }, stun: 0, playSound: false);
|
||||
patient1.AIController.Enabled = false;
|
||||
|
||||
assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("assistant"));
|
||||
assistantInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("assistant"));
|
||||
patient2 = Character.Create(assistantInfo, patientHull2.WorldPosition, "2");
|
||||
patient2.TeamID = CharacterTeamType.Team1;
|
||||
patient2.GiveJobItems(null);
|
||||
patient2.CanSpeak = false;
|
||||
patient2.AIController.Enabled = false;
|
||||
|
||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer"));
|
||||
var mechanicInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer"));
|
||||
var subPatient1 = Character.Create(mechanicInfo, WayPoint.GetRandom(SpawnType.Human, mechanicInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "3");
|
||||
subPatient1.TeamID = CharacterTeamType.Team1;
|
||||
subPatient1.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 40.0f) }, stun: 0, playSound: false);
|
||||
subPatients.Add(subPatient1);
|
||||
|
||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("securityofficer"));
|
||||
var securityInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("securityofficer"));
|
||||
var subPatient2 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, securityInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "3");
|
||||
subPatient2.TeamID = CharacterTeamType.Team1;
|
||||
subPatient2.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.InternalDamage, 40.0f) }, stun: 0, playSound: false);
|
||||
subPatients.Add(subPatient2);
|
||||
|
||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer"));
|
||||
var engineerInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: JobPrefab.Get("engineer"));
|
||||
var subPatient3 = Character.Create(securityInfo, WayPoint.GetRandom(SpawnType.Human, engineerInfo.Job?.Prefab, Submarine.MainSub).WorldPosition, "3");
|
||||
subPatient3.TeamID = CharacterTeamType.Team1;
|
||||
subPatient3.AddDamage(patient1.WorldPosition, new List<Affliction>() { new Affliction(AfflictionPrefab.Burn, 20.0f) }, stun: 0, playSound: false);
|
||||
@@ -196,7 +248,7 @@ namespace Barotrauma.Tutorials
|
||||
yield return new WaitForSeconds(2.0f);
|
||||
}*/
|
||||
|
||||
TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Medical supplies objective
|
||||
TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.ToggleInventory)); // Medical supplies objective
|
||||
|
||||
do
|
||||
{
|
||||
@@ -215,24 +267,24 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
} while (doctor.Inventory.FindItemByIdentifier("antidama1") == null); // Wait until looted
|
||||
} while (doctor.Inventory.FindItemByIdentifier("antidama1".ToIdentifier()) == null); // Wait until looted
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
|
||||
SetHighlight(doctor_suppliesCabinet.Item, false);
|
||||
RemoveCompletedObjective(segments[0]);
|
||||
RemoveCompletedObjective(0);
|
||||
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
|
||||
// 2nd tutorial segment, treat self -------------------------------------------------------------------------
|
||||
|
||||
TriggerTutorialSegment(1, GameMain.Config.KeyBindText(InputType.Health)); // Open health interface
|
||||
TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // Open health interface
|
||||
while (CharacterHealth.OpenHealthWindow == null)
|
||||
{
|
||||
doctor.CharacterHealth.HealthBarPulsateTimer = 1.0f;
|
||||
yield return null;
|
||||
}
|
||||
yield return null;
|
||||
RemoveCompletedObjective(segments[1]);
|
||||
RemoveCompletedObjective(1);
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
TriggerTutorialSegment(2); //Treat self
|
||||
while (doctor.CharacterHealth.GetAfflictionStrength("damage") > 0.01f)
|
||||
@@ -243,13 +295,13 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
else
|
||||
{
|
||||
HighlightInventorySlot(doctor.Inventory, "antidama1", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(doctor.Inventory, "antidama1".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
RemoveCompletedObjective(segments[2]);
|
||||
RemoveCompletedObjective(2);
|
||||
SetDoorAccess(doctor_firstDoor, doctor_firstDoorLight, true);
|
||||
|
||||
while (CharacterHealth.OpenHealthWindow != null)
|
||||
@@ -260,10 +312,10 @@ namespace Barotrauma.Tutorials
|
||||
// treat patient --------------------------------------------------------------------------------------------
|
||||
|
||||
//patient 1 requests first aid
|
||||
var newOrder = new Order(Order.GetPrefab("requestfirstaid"), patient1.CurrentHull, null, orderGiver: patient1);
|
||||
var newOrder = new Order(OrderPrefab.Prefabs["requestfirstaid"], patient1.CurrentHull, null, orderGiver: patient1);
|
||||
doctor.AddActiveObjectiveEntity(patient1, doctor_firstAidIcon, doctor_firstAidIconColor);
|
||||
//GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient1.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order, null);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient1.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName?.Value, givingOrderToSelf: false), ChatMessageType.Order, null);
|
||||
|
||||
while (doctor.CurrentHull != patient1.CurrentHull)
|
||||
{
|
||||
@@ -281,9 +333,9 @@ namespace Barotrauma.Tutorials
|
||||
yield return new WaitForSeconds(3.0f, false);
|
||||
patient1.AIController.Enabled = true;
|
||||
doctor.RemoveActiveObjectiveEntity(patient1);
|
||||
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Command)); // Get the patient to medbay
|
||||
TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Command)); // Get the patient to medbay
|
||||
|
||||
while (patient1.GetCurrentOrderWithTopPriority()?.Order?.Identifier != "follow")
|
||||
while (patient1.GetCurrentOrderWithTopPriority()?.Identifier != "follow")
|
||||
{
|
||||
// TODO: Rework order highlighting for new command UI
|
||||
// GameMain.GameSession.CrewManager.HighlightOrderButton(patient1, "follow", highlightColor, new Vector2(5, 5));
|
||||
@@ -296,14 +348,14 @@ namespace Barotrauma.Tutorials
|
||||
{
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
}
|
||||
RemoveCompletedObjective(segments[3]);
|
||||
RemoveCompletedObjective(3);
|
||||
SetHighlight(doctor_medBayCabinet.Item, true);
|
||||
SetDoorAccess(doctor_thirdDoor, doctor_thirdDoorLight, true);
|
||||
patient1.CharacterHealth.UseHealthWindow = true;
|
||||
|
||||
yield return new WaitForSeconds(2.0f, false);
|
||||
|
||||
TriggerTutorialSegment(4, GameMain.Config.KeyBindText(InputType.Health)); // treat burns
|
||||
TriggerTutorialSegment(4, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // treat burns
|
||||
|
||||
do
|
||||
{
|
||||
@@ -322,7 +374,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
} while (doctor.Inventory.FindItemByIdentifier("antibleeding1") == null); // Wait until looted
|
||||
} while (doctor.Inventory.FindItemByIdentifier("antibleeding1".ToIdentifier()) == null); // Wait until looted
|
||||
SetHighlight(doctor_medBayCabinet.Item, false);
|
||||
SetHighlight(patient1, true);
|
||||
|
||||
@@ -334,12 +386,12 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
else
|
||||
{
|
||||
HighlightInventorySlot(doctor.Inventory, "antibleeding1", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(doctor.Inventory, "antibleeding1".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
yield return null;
|
||||
|
||||
}
|
||||
RemoveCompletedObjective(segments[4]);
|
||||
RemoveCompletedObjective(4);
|
||||
SetHighlight(patient1, false);
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
|
||||
@@ -350,10 +402,10 @@ namespace Barotrauma.Tutorials
|
||||
//patient calls for help
|
||||
//patient2.CanSpeak = true;
|
||||
yield return new WaitForSeconds(2.0f, false);
|
||||
newOrder = new Order(Order.GetPrefab("requestfirstaid"), patient2.CurrentHull, null, orderGiver: patient2);
|
||||
newOrder = new Order(OrderPrefab.Prefabs["requestfirstaid"], patient2.CurrentHull, null, orderGiver: patient2);
|
||||
doctor.AddActiveObjectiveEntity(patient2, doctor_firstAidIcon, doctor_firstAidIconColor);
|
||||
//GameMain.GameSession.CrewManager.AddOrder(newOrder, newOrder.FadeOutTime);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient2.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName, givingOrderToSelf: false), ChatMessageType.Order, null);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(patient2.Name, newOrder.GetChatMessage("", patient1.CurrentHull?.DisplayName?.Value, givingOrderToSelf: false), ChatMessageType.Order, null);
|
||||
patient2.AIController.Enabled = true;
|
||||
patient2.Oxygen = -50;
|
||||
CoroutineManager.StartCoroutine(KeepPatientAlive(patient2), "KeepPatient2Alive");
|
||||
@@ -365,7 +417,7 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!tutorial_upperFinalDoor.IsOpen);
|
||||
yield return new WaitForSeconds(2.0f, false);
|
||||
|
||||
TriggerTutorialSegment(5, GameMain.Config.KeyBindText(InputType.Health)); // perform CPR
|
||||
TriggerTutorialSegment(5, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // perform CPR
|
||||
SetHighlight(patient2, true);
|
||||
while (patient2.IsUnconscious)
|
||||
{
|
||||
@@ -380,7 +432,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
yield return null;
|
||||
}
|
||||
RemoveCompletedObjective(segments[5]);
|
||||
RemoveCompletedObjective(5);
|
||||
SetHighlight(patient2, false);
|
||||
doctor.RemoveActiveObjectiveEntity(patient2);
|
||||
CoroutineManager.StopCoroutines("KeepPatient2Alive");
|
||||
@@ -399,7 +451,7 @@ namespace Barotrauma.Tutorials
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Doctor.Radio.EnteredSub"), ChatMessageType.Radio, null);
|
||||
|
||||
yield return new WaitForSeconds(3.0f, false);
|
||||
TriggerTutorialSegment(6, GameMain.Config.KeyBindText(InputType.Health)); // give treatment to anyone in need
|
||||
TriggerTutorialSegment(6, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Health)); // give treatment to anyone in need
|
||||
|
||||
foreach (var patient in subPatients)
|
||||
{
|
||||
@@ -421,8 +473,8 @@ namespace Barotrauma.Tutorials
|
||||
if (!patientCalledHelp[i] && Timing.TotalTime > subEnterTime + 60 * (i + 1))
|
||||
{
|
||||
doctor.AddActiveObjectiveEntity(subPatients[i], doctor_firstAidIcon, doctor_firstAidIconColor);
|
||||
newOrder = new Order(Order.GetPrefab("requestfirstaid"), subPatients[i].CurrentHull, null, orderGiver: subPatients[i]);
|
||||
string message = newOrder.GetChatMessage("", subPatients[i].CurrentHull?.DisplayName, givingOrderToSelf: false);
|
||||
newOrder = new Order(OrderPrefab.Prefabs["requestfirstaid"], subPatients[i].CurrentHull, null, orderGiver: subPatients[i]);
|
||||
string message = newOrder.GetChatMessage("", subPatients[i].CurrentHull?.DisplayName?.Value, givingOrderToSelf: false);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(subPatients[i].Name, message, ChatMessageType.Order, null);
|
||||
patientCalledHelp[i] = true;
|
||||
}
|
||||
@@ -435,7 +487,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
yield return new WaitForSeconds(1.0f, false);
|
||||
}
|
||||
RemoveCompletedObjective(segments[6]);
|
||||
RemoveCompletedObjective(6);
|
||||
foreach (var patient in subPatients)
|
||||
{
|
||||
SetHighlight(patient, false);
|
||||
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
class EditorTutorial : Tutorial
|
||||
{
|
||||
public EditorTutorial(XElement element)
|
||||
: base (element)
|
||||
{
|
||||
}
|
||||
|
||||
public override IEnumerable<CoroutineStatus> UpdateState()
|
||||
{
|
||||
/*infoBox = CreateInfoFrame("Use the mouse wheel to zoom in and out, and WASD to move the camera around.", true);
|
||||
|
||||
while (infoBox != null)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Press \"Structure\" at the left side of the screen to start placing some walls.");
|
||||
|
||||
while (GameMain.SubEditorScreen.SelectedTab != (int)MapEntityCategory.Structure)
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("Select \"topwall\" from the list.", true);
|
||||
|
||||
while (MapEntityPrefab.Selected == null || MapEntityPrefab.Selected.Name != "topwall")
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame("You can now create a horizontal wall by clicking and dragging. When you're done, right click to stop creating walls.");*/
|
||||
|
||||
|
||||
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
}
|
||||
}
|
||||
+73
-26
@@ -62,7 +62,7 @@ namespace Barotrauma.Tutorials
|
||||
private Reactor engineer_submarineReactor;
|
||||
|
||||
// Variables
|
||||
private string radioSpeakerName;
|
||||
private LocalizedString radioSpeakerName;
|
||||
private Character engineer;
|
||||
private int[] reactorLoads = new int[5] { 1500, 3000, 2000, 5000, 3500 };
|
||||
private float reactorLoadChangeTime = 2f;
|
||||
@@ -75,27 +75,74 @@ namespace Barotrauma.Tutorials
|
||||
private Color engineer_reactorIconColor;
|
||||
private bool wiringActive = false;
|
||||
|
||||
public EngineerTutorial(XElement element) : base(element)
|
||||
{
|
||||
public EngineerTutorial() : base("tutorial.engineertraining".ToIdentifier(),
|
||||
new Segment(
|
||||
"Mechanic.Equipment".ToIdentifier(),
|
||||
"Mechanic.EquipmentObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Engineer.Reactor".ToIdentifier(),
|
||||
"Engineer.ReactorObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Engineer.ReactorText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_reactor.webm", TextTag = "Engineer.ReactorText".ToIdentifier(), Width = 700, Height = 80 }),
|
||||
new Segment(
|
||||
"Engineer.OperateReactor".ToIdentifier(),
|
||||
"Engineer.OperateReactorObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Engineer.OperateReactorText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_reactor.webm", TextTag = "Engineer.ReactorText".ToIdentifier(), Width = 700, Height = 80 }),
|
||||
new Segment(
|
||||
"Engineer.RepairJunctionBox".ToIdentifier(),
|
||||
"Engineer.RepairJunctionBoxObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Engineer.RepairJunctionBoxText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Engineer.WireJunctionBoxes".ToIdentifier(),
|
||||
"Engineer.WireJunctionBoxesObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Engineer.WireJunctionBoxesText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_wiring.webm", TextTag = "Engineer.WireJunctionBoxesText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Engineer.RepairElectricalRoom".ToIdentifier(),
|
||||
"Engineer.RepairElectricalRoomObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Engineer.RepairElectricalRoomText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Engineer.PowerUpReactor".ToIdentifier(),
|
||||
"Engineer.PowerUpReactorObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Engineer.PowerUpReactorText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center }))
|
||||
{ }
|
||||
|
||||
protected override CharacterInfo GetCharacterInfo()
|
||||
{
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 0),
|
||||
new Skill("weapons".ToIdentifier(), 0),
|
||||
new Skill("mechanical".ToIdentifier(), 20),
|
||||
new Skill("electrical".ToIdentifier(), 60),
|
||||
new Skill("helm".ToIdentifier(), 0)));
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker");
|
||||
engineer = Character.Controlled;
|
||||
|
||||
var toolbelt = FindOrGiveItem(engineer, "toolbelt");
|
||||
var toolbelt = FindOrGiveItem(engineer, "toolbelt".ToIdentifier());
|
||||
toolbelt.Unequip(engineer);
|
||||
engineer.Inventory.RemoveItem(toolbelt);
|
||||
|
||||
var repairOrder = Order.GetPrefab("repairsystems");
|
||||
var repairOrder = OrderPrefab.Prefabs["repairsystems"];
|
||||
engineer_repairIcon = repairOrder.SymbolSprite;
|
||||
engineer_repairIconColor = repairOrder.Color;
|
||||
|
||||
var reactorOrder = Order.GetPrefab("operatereactor");
|
||||
var reactorOrder = OrderPrefab.Prefabs["operatereactor"];
|
||||
engineer_reactorIcon = reactorOrder.SymbolSprite;
|
||||
engineer_reactorIconColor = reactorOrder.Color;
|
||||
|
||||
@@ -235,7 +282,7 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!engineer_equipmentObjectiveSensor.MotionDetected);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.Equipment"), ChatMessageType.Radio, null);
|
||||
yield return new WaitForSeconds(0.5f, false);
|
||||
TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Retrieve equipment
|
||||
TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.ToggleInventory)); // Retrieve equipment
|
||||
bool firstSlotRemoved = false;
|
||||
bool secondSlotRemoved = false;
|
||||
bool thirdSlotRemoved = false;
|
||||
@@ -276,7 +323,7 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
yield return null;
|
||||
} while (!engineer_equipmentCabinet.Inventory.IsEmpty()); // Wait until looted
|
||||
RemoveCompletedObjective(segments[0]);
|
||||
RemoveCompletedObjective(0);
|
||||
SetHighlight(engineer_equipmentCabinet.Item, false);
|
||||
SetHighlight(engineer_reactor.Item, true);
|
||||
SetDoorAccess(engineer_firstDoor, engineer_firstDoorLight, true);
|
||||
@@ -302,7 +349,7 @@ namespace Barotrauma.Tutorials
|
||||
if (IsSelectedItem(engineer_reactor.Item) && engineer_reactor.Item.OwnInventory.visualSlots != null)
|
||||
{
|
||||
engineer_reactor.AutoTemp = false;
|
||||
HighlightInventorySlot(engineer.Inventory, "fuelrod", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(engineer.Inventory, "fuelrod".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
|
||||
for (int i = 0; i < engineer_reactor.Item.OwnInventory.visualSlots.Length; i++)
|
||||
{
|
||||
@@ -311,7 +358,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
yield return null;
|
||||
} while (engineer_reactor.AvailableFuel == 0);
|
||||
RemoveCompletedObjective(segments[1]);
|
||||
RemoveCompletedObjective(1);
|
||||
TriggerTutorialSegment(2);
|
||||
CoroutineManager.StartCoroutine(ReactorOperatedProperly());
|
||||
do
|
||||
@@ -354,7 +401,7 @@ namespace Barotrauma.Tutorials
|
||||
} while (wait > 0.0f);
|
||||
engineer.SelectedConstruction = null;
|
||||
engineer_reactor.CanBeSelected = false;
|
||||
RemoveCompletedObjective(segments[2]);
|
||||
RemoveCompletedObjective(2);
|
||||
SetHighlight(engineer_reactor.Item, false);
|
||||
SetHighlight(engineer_brokenJunctionBox, true);
|
||||
SetDoorAccess(engineer_secondDoor, engineer_secondDoorLight, true);
|
||||
@@ -363,12 +410,12 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!engineer_secondDoor.IsOpen);
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
Repairable repairableJunctionBoxComponent = engineer_brokenJunctionBox.GetComponent<Repairable>();
|
||||
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Select)); // Repair the junction box
|
||||
TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select)); // Repair the junction box
|
||||
do
|
||||
{
|
||||
if (!engineer.HasEquippedItem("screwdriver"))
|
||||
if (!engineer.HasEquippedItem("screwdriver".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(engineer.Inventory, "screwdriver", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(engineer.Inventory, "screwdriver".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
else if (IsSelectedItem(engineer_brokenJunctionBox) && repairableJunctionBoxComponent.CurrentFixer == null)
|
||||
{
|
||||
@@ -380,7 +427,7 @@ namespace Barotrauma.Tutorials
|
||||
yield return null;
|
||||
} while (repairableJunctionBoxComponent.IsBelowRepairThreshold); // Wait until repaired
|
||||
SetHighlight(engineer_brokenJunctionBox, false);
|
||||
RemoveCompletedObjective(segments[3]);
|
||||
RemoveCompletedObjective(3);
|
||||
SetDoorAccess(engineer_thirdDoor, engineer_thirdDoorLight, true);
|
||||
for (int i = 0; i < engineer_disconnectedJunctionBoxes.Length; i++)
|
||||
{
|
||||
@@ -391,14 +438,14 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!engineer_thirdDoor.IsOpen);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.FaultyWiring"), ChatMessageType.Radio, null);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
TriggerTutorialSegment(4, GameMain.Config.KeyBindText(InputType.Use), GameMain.Config.KeyBindText(InputType.Deselect)); // Connect the junction boxes
|
||||
TriggerTutorialSegment(4, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Use), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect)); // Connect the junction boxes
|
||||
do { CheckGhostWires(); HandleJunctionBoxWiringHighlights(); yield return null; } while (engineer_workingPump.Voltage < engineer_workingPump.MinVoltage); // Wait until connected all the way to the pump
|
||||
CheckGhostWires();
|
||||
for (int i = 0; i < engineer_disconnectedJunctionBoxes.Length; i++)
|
||||
{
|
||||
SetHighlight(engineer_disconnectedJunctionBoxes[i].Item, false);
|
||||
}
|
||||
RemoveCompletedObjective(segments[4]);
|
||||
RemoveCompletedObjective(4);
|
||||
do { yield return null; } while (engineer_workingPump.Item.CurrentHull.WaterPercentage > waterVolumeBeforeOpening); // Wait until drained
|
||||
wiringActive = false;
|
||||
SetDoorAccess(engineer_fourthDoor, engineer_fourthDoorLight, true);
|
||||
@@ -424,7 +471,7 @@ namespace Barotrauma.Tutorials
|
||||
// Remove highlights when each individual machine is repaired
|
||||
do { CheckJunctionBoxHighlights(repairableJunctionBoxComponent1, repairableJunctionBoxComponent2, repairableJunctionBoxComponent3); yield return null; } while (repairableJunctionBoxComponent1.IsBelowRepairThreshold || repairableJunctionBoxComponent2.IsBelowRepairThreshold || repairableJunctionBoxComponent3.IsBelowRepairThreshold);
|
||||
CheckJunctionBoxHighlights(repairableJunctionBoxComponent1, repairableJunctionBoxComponent2, repairableJunctionBoxComponent3);
|
||||
RemoveCompletedObjective(segments[5]);
|
||||
RemoveCompletedObjective(5);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
|
||||
TriggerTutorialSegment(6); // Powerup reactor
|
||||
@@ -433,7 +480,7 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!IsReactorPoweredUp(engineer_submarineReactor)); // Wait until ~matches load
|
||||
engineer.RemoveActiveObjectiveEntity(engineer_submarineReactor.Item);
|
||||
SetHighlight(engineer_submarineReactor.Item, false);
|
||||
RemoveCompletedObjective(segments[6]);
|
||||
RemoveCompletedObjective(6);
|
||||
GameMain.GameSession.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Engineer.Radio.Complete"), ChatMessageType.Radio, null);
|
||||
|
||||
yield return new WaitForSeconds(4f, false);
|
||||
@@ -516,9 +563,9 @@ namespace Barotrauma.Tutorials
|
||||
{
|
||||
Item selected = engineer.SelectedConstruction;
|
||||
|
||||
if (!engineer.HasEquippedItem("screwdriver"))
|
||||
if (!engineer.HasEquippedItem("screwdriver".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(engineer.Inventory, "screwdriver", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(engineer.Inventory, "screwdriver".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
}
|
||||
|
||||
int selectedIndex = -1;
|
||||
@@ -537,9 +584,9 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
wiringActive = selectedIndex != -1;
|
||||
|
||||
if (!engineer.HasEquippedItem("wire"))
|
||||
if (!engineer.HasEquippedItem("wire".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlotWithTag(engineer.Inventory, "wire", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlotWithTag(engineer.Inventory, "wire".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+136
-62
@@ -69,33 +69,106 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
// Variables
|
||||
private const float waterVolumeBeforeOpening = 15f;
|
||||
private string radioSpeakerName;
|
||||
private LocalizedString radioSpeakerName;
|
||||
private Character mechanic;
|
||||
private Sprite mechanic_repairIcon;
|
||||
private Color mechanic_repairIconColor;
|
||||
private Sprite mechanic_weldIcon;
|
||||
|
||||
public MechanicTutorial(XElement element) : base(element)
|
||||
{
|
||||
public MechanicTutorial() : base("tutorial.mechanictraining".ToIdentifier(),
|
||||
new Segment(
|
||||
"Mechanic.OpenDoor".ToIdentifier(),
|
||||
"Mechanic.OpenDoorObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.OpenDoorText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.Equipment".ToIdentifier(),
|
||||
"Mechanic.EquipmentObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_inventory.webm", TextTag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Mechanic.Welding".ToIdentifier(),
|
||||
"Mechanic.WeldingObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.WeldingText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_equip.webm", TextTag = "Mechanic.WeldingText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Mechanic.Drain".ToIdentifier(),
|
||||
"Mechanic.DrainObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.DrainText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.Deconstruct".ToIdentifier(),
|
||||
"Mechanic.DeconstructObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.DeconstructText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_deconstruct.webm", TextTag = "Mechanic.DeconstructText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Mechanic.Fabricate".ToIdentifier(),
|
||||
"Mechanic.FabricateObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.FabricateText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_fabricate.webm", TextTag = "Mechanic.FabricateText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Mechanic.Extinguisher".ToIdentifier(),
|
||||
"Mechanic.ExtinguisherObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.ExtinguisherText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.DropExtinguisher".ToIdentifier(),
|
||||
"Mechanic.DropExtinguisherObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.DropExtinguisherText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.Diving".ToIdentifier(),
|
||||
"Mechanic.DivingObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.DivingText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.RepairPump".ToIdentifier(),
|
||||
"Mechanic.RepairPumpObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.RepairPumpText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Mechanic.RepairSubmarine".ToIdentifier(),
|
||||
"Mechanic.RepairSubmarineObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.RepairSubmarineText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"tutorial.laddertitle".ToIdentifier(),
|
||||
"tutorial.laddertitle".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "tutorial.ladderdescription".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }))
|
||||
{ }
|
||||
|
||||
protected override CharacterInfo GetCharacterInfo()
|
||||
{
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 0),
|
||||
new Skill("weapons".ToIdentifier(), 0),
|
||||
new Skill("mechanical".ToIdentifier(), 50),
|
||||
new Skill("electrical".ToIdentifier(), 20),
|
||||
new Skill("helm".ToIdentifier(), 0)));
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker");
|
||||
mechanic = Character.Controlled;
|
||||
|
||||
var toolbelt = FindOrGiveItem(mechanic, "toolbelt");
|
||||
var toolbelt = FindOrGiveItem(mechanic, "toolbelt".ToIdentifier());
|
||||
toolbelt.Unequip(mechanic);
|
||||
mechanic.Inventory.RemoveItem(toolbelt);
|
||||
|
||||
var crowbar = FindOrGiveItem(mechanic, "crowbar");
|
||||
var crowbar = FindOrGiveItem(mechanic, "crowbar".ToIdentifier());
|
||||
crowbar.Unequip(mechanic);
|
||||
mechanic.Inventory.RemoveItem(crowbar);
|
||||
|
||||
var repairOrder = Order.GetPrefab("repairsystems");
|
||||
var repairOrder = OrderPrefab.Prefabs["repairsystems"];
|
||||
mechanic_repairIcon = repairOrder.SymbolSprite;
|
||||
mechanic_repairIconColor = repairOrder.Color;
|
||||
mechanic_weldIcon = new Sprite("Content/UI/MainIconsAtlas.png", new Rectangle(1, 256, 127, 127), new Vector2(0.5f, 0.5f));
|
||||
@@ -239,24 +312,25 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
yield return new WaitForSeconds(2.5f, false);
|
||||
|
||||
mechanic_fabricator.RemoveFabricationRecipes(new List<string>() { "extinguisher", "wrench", "weldingtool", "weldingfuel", "divingmask", "railgunshell", "nuclearshell", "uex", "harpoongun" });
|
||||
mechanic_fabricator.RemoveFabricationRecipes(allowedIdentifiers:
|
||||
new[] { "extinguisher", "wrench", "weldingtool", "weldingfuel", "divingmask", "railgunshell", "nuclearshell", "uex", "harpoongun" }.ToIdentifiers());
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.WakeUp"), ChatMessageType.Radio, null);
|
||||
|
||||
yield return new WaitForSeconds(2.5f, false);
|
||||
TriggerTutorialSegment(0, GameMain.Config.KeyBindText(InputType.Up), GameMain.Config.KeyBindText(InputType.Left), GameMain.Config.KeyBindText(InputType.Down), GameMain.Config.KeyBindText(InputType.Right), GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Select)); // Open door objective
|
||||
TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Up), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Left), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Down), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Right), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select)); // Open door objective
|
||||
yield return new WaitForSeconds(0.0f, false);
|
||||
SetDoorAccess(mechanic_firstDoor, mechanic_firstDoorLight, true);
|
||||
SetHighlight(mechanic_firstDoor.Item, true);
|
||||
do { yield return null; } while (!mechanic_firstDoor.IsOpen);
|
||||
SetHighlight(mechanic_firstDoor.Item, false);
|
||||
yield return new WaitForSeconds(1.5f, false);
|
||||
RemoveCompletedObjective(segments[0]);
|
||||
RemoveCompletedObjective(0);
|
||||
|
||||
// Room 2
|
||||
yield return new WaitForSeconds(0.0f, false);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Equipment"), ChatMessageType.Radio, null);
|
||||
do { yield return null; } while (!mechanic_equipmentObjectiveSensor.MotionDetected);
|
||||
TriggerTutorialSegment(1, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Deselect), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Equipment & inventory objective
|
||||
TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.ToggleInventory)); // Equipment & inventory objective
|
||||
SetHighlight(mechanic_equipmentCabinet.Item, true);
|
||||
bool firstSlotRemoved = false;
|
||||
bool secondSlotRemoved = false;
|
||||
@@ -290,35 +364,35 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
|
||||
yield return null;
|
||||
} while (mechanic.Inventory.FindItemByIdentifier("divingmask") == null || mechanic.Inventory.FindItemByIdentifier("weldingtool") == null || mechanic.Inventory.FindItemByIdentifier("wrench") == null); // Wait until looted
|
||||
} while (mechanic.Inventory.FindItemByIdentifier("divingmask".ToIdentifier()) == null || mechanic.Inventory.FindItemByIdentifier("weldingtool".ToIdentifier()) == null || mechanic.Inventory.FindItemByIdentifier("wrench".ToIdentifier()) == null); // Wait until looted
|
||||
SetHighlight(mechanic_equipmentCabinet.Item, false);
|
||||
yield return new WaitForSeconds(1.5f, false);
|
||||
RemoveCompletedObjective(segments[1]);
|
||||
RemoveCompletedObjective(1);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Breach"), ChatMessageType.Radio, null);
|
||||
|
||||
// Room 3
|
||||
do { yield return null; } while (!mechanic_weldingObjectiveSensor.MotionDetected);
|
||||
TriggerTutorialSegment(2, GameMain.Config.KeyBindText(InputType.Aim), GameMain.Config.KeyBindText(InputType.Shoot), GameMain.Config.KeyBindText(InputType.ToggleInventory)); // Welding objective
|
||||
TriggerTutorialSegment(2, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.ToggleInventory)); // Welding objective
|
||||
do
|
||||
{
|
||||
if (!mechanic.HasEquippedItem("divingmask"))
|
||||
if (!mechanic.HasEquippedItem("divingmask".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "divingmask", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "divingmask".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
|
||||
if (!mechanic.HasEquippedItem("weldingtool"))
|
||||
if (!mechanic.HasEquippedItem("weldingtool".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "weldingtool", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "weldingtool".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
yield return null;
|
||||
} while (!mechanic.HasEquippedItem("divingmask") || !mechanic.HasEquippedItem("weldingtool")); // Wait until equipped
|
||||
} while (!mechanic.HasEquippedItem("divingmask".ToIdentifier()) || !mechanic.HasEquippedItem("weldingtool".ToIdentifier())); // Wait until equipped
|
||||
SetDoorAccess(mechanic_secondDoor, mechanic_secondDoorLight, true);
|
||||
mechanic.AddActiveObjectiveEntity(mechanic_brokenWall_1, mechanic_weldIcon, mechanic_repairIconColor);
|
||||
do { yield return null; } while (WallHasDamagedSections(mechanic_brokenWall_1)); // Highlight until repaired
|
||||
mechanic.RemoveActiveObjectiveEntity(mechanic_brokenWall_1);
|
||||
RemoveCompletedObjective(segments[2]);
|
||||
RemoveCompletedObjective(2);
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
TriggerTutorialSegment(3, GameMain.Config.KeyBindText(InputType.Select)); // Pump objective
|
||||
TriggerTutorialSegment(3, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select)); // Pump objective
|
||||
SetHighlight(mechanic_workingPump.Item, true);
|
||||
do
|
||||
{
|
||||
@@ -333,9 +407,9 @@ namespace Barotrauma.Tutorials
|
||||
} while (mechanic_workingPump.FlowPercentage >= 0 || !mechanic_workingPump.IsActive); // Highlight until draining
|
||||
SetHighlight(mechanic_workingPump.Item, false);
|
||||
do { yield return null; } while (mechanic_brokenhull_1.WaterPercentage > waterVolumeBeforeOpening); // Unlock door once drained
|
||||
RemoveCompletedObjective(segments[3]);
|
||||
RemoveCompletedObjective(3);
|
||||
SetDoorAccess(mechanic_thirdDoor, mechanic_thirdDoorLight, true);
|
||||
//TriggerTutorialSegment(11, GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Up), GameMain.Config.KeyBind(InputType.Down), GameMain.Config.KeyBind(InputType.Select)); // Ladder objective
|
||||
//TriggerTutorialSegment(11, GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Up], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Down], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select]); // Ladder objective
|
||||
//do { yield return null; } while (!mechanic_ladderSensor.MotionDetected);
|
||||
//RemoveCompletedObjective(segments[11]);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.News"), ChatMessageType.Radio, null);
|
||||
@@ -362,24 +436,24 @@ namespace Barotrauma.Tutorials
|
||||
if (mechanic.Inventory.GetItemAt(i) == null) { HighlightInventorySlot(mechanic.Inventory, i, highlightColor, .5f, .5f, 0f); }
|
||||
}
|
||||
|
||||
if (mechanic.Inventory.FindItemByIdentifier("oxygentank") == null && mechanic.Inventory.FindItemByIdentifier("aluminium") == null)
|
||||
if (mechanic.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) == null && mechanic.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) == null)
|
||||
{
|
||||
for (int i = 0; i < mechanic_craftingCabinet.Capacity; i++)
|
||||
{
|
||||
Item item = mechanic_craftingCabinet.Inventory.GetItemAt(i);
|
||||
if (item != null && item.prefab.Identifier == "oxygentank")
|
||||
if (item != null && item.Prefab.Identifier == "oxygentank")
|
||||
{
|
||||
HighlightInventorySlot(mechanic_craftingCabinet.Inventory, i, highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mechanic.Inventory.FindItemByIdentifier("sodium") == null)
|
||||
if (mechanic.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) == null)
|
||||
{
|
||||
for (int i = 0; i < mechanic_craftingCabinet.Inventory.Capacity; i++)
|
||||
{
|
||||
Item item = mechanic_craftingCabinet.Inventory.GetItemAt(i);
|
||||
if (item != null && item.prefab.Identifier == "sodium")
|
||||
if (item != null && item.Prefab.Identifier == "sodium")
|
||||
{
|
||||
HighlightInventorySlot(mechanic_craftingCabinet.Inventory, i, highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
@@ -387,12 +461,12 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
|
||||
if (!gotOxygenTank && (mechanic.Inventory.FindItemByIdentifier("oxygentank") != null ||
|
||||
mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank") != null))
|
||||
if (!gotOxygenTank && (mechanic.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null ||
|
||||
mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null))
|
||||
{
|
||||
gotOxygenTank = true;
|
||||
}
|
||||
if (!gotSodium && mechanic.Inventory.FindItemByIdentifier("sodium") != null)
|
||||
if (!gotSodium && mechanic.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) != null)
|
||||
{
|
||||
gotSodium = true;
|
||||
}
|
||||
@@ -406,9 +480,9 @@ namespace Barotrauma.Tutorials
|
||||
{
|
||||
if (IsSelectedItem(mechanic_deconstructor.Item))
|
||||
{
|
||||
if (mechanic_deconstructor.OutputContainer.Inventory.FindItemByIdentifier("aluminium") != null)
|
||||
if (mechanic_deconstructor.OutputContainer.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) != null)
|
||||
{
|
||||
HighlightInventorySlot(mechanic_deconstructor.OutputContainer.Inventory, "aluminium", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic_deconstructor.OutputContainer.Inventory, "aluminium".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
|
||||
for (int i = 0; i < mechanic.Inventory.Capacity; i++)
|
||||
{
|
||||
@@ -417,16 +491,16 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mechanic.Inventory.FindItemByIdentifier("oxygentank") != null && mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank") == null)
|
||||
if (mechanic.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null && mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) == null)
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "oxygentank", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "oxygentank".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
for (int i = 0; i < mechanic_deconstructor.InputContainer.Inventory.Capacity; i++)
|
||||
{
|
||||
HighlightInventorySlot(mechanic_deconstructor.InputContainer.Inventory, i, highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
if (mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank") != null && !mechanic_deconstructor.IsActive)
|
||||
if (mechanic_deconstructor.InputContainer.Inventory.FindItemByIdentifier("oxygentank".ToIdentifier()) != null && !mechanic_deconstructor.IsActive)
|
||||
{
|
||||
if (mechanic_deconstructor.ActivateButton.FlashTimer <= 0)
|
||||
{
|
||||
@@ -437,11 +511,11 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
yield return null;
|
||||
} while (
|
||||
mechanic.Inventory.FindItemByIdentifier("aluminium") == null &&
|
||||
mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("aluminium") == null); // Wait until aluminium obtained
|
||||
mechanic.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) == null &&
|
||||
mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) == null); // Wait until aluminium obtained
|
||||
|
||||
SetHighlight(mechanic_deconstructor.Item, false);
|
||||
RemoveCompletedObjective(segments[4]);
|
||||
SetHighlight(mechanic_deconstructor.Item, false);
|
||||
RemoveCompletedObjective(4);
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
TriggerTutorialSegment(5); // Fabricate
|
||||
SetHighlight(mechanic_fabricator.Item, true);
|
||||
@@ -455,26 +529,26 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mechanic_fabricator.OutputContainer.Inventory.FindItemByIdentifier("extinguisher") != null)
|
||||
if (mechanic_fabricator.OutputContainer.Inventory.FindItemByIdentifier("extinguisher".ToIdentifier()) != null)
|
||||
{
|
||||
HighlightInventorySlot(mechanic_fabricator.OutputContainer.Inventory, "extinguisher", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic_fabricator.OutputContainer.Inventory, "extinguisher".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
|
||||
/*for (int i = 0; i < mechanic.Inventory.Capacity; i++)
|
||||
{
|
||||
if (mechanic.Inventory.Items[i] == null) HighlightInventorySlot(mechanic.Inventory, i, highlightColor, .5f, .5f, 0f);
|
||||
}*/
|
||||
}
|
||||
else if (mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("aluminium") != null && mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("sodium") != null && !mechanic_fabricator.IsActive)
|
||||
else if (mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) != null && mechanic_fabricator.InputContainer.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) != null && !mechanic_fabricator.IsActive)
|
||||
{
|
||||
if (mechanic_fabricator.ActivateButton.FlashTimer <= 0)
|
||||
{
|
||||
mechanic_fabricator.ActivateButton.Flash(highlightColor, 1.5f, false);
|
||||
}
|
||||
}
|
||||
else if (mechanic.Inventory.FindItemByIdentifier("aluminium") != null || mechanic.Inventory.FindItemByIdentifier("sodium") != null)
|
||||
else if (mechanic.Inventory.FindItemByIdentifier("aluminium".ToIdentifier()) != null || mechanic.Inventory.FindItemByIdentifier("sodium".ToIdentifier()) != null)
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "aluminium", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "sodium", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "aluminium".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "sodium".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
|
||||
if (mechanic_fabricator.InputContainer.Inventory.GetItemAt(0) == null)
|
||||
{
|
||||
@@ -489,27 +563,27 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
} while (mechanic.Inventory.FindItemByIdentifier("extinguisher") == null); // Wait until extinguisher is created
|
||||
RemoveCompletedObjective(segments[5]);
|
||||
} while (mechanic.Inventory.FindItemByIdentifier("extinguisher".ToIdentifier()) == null); // Wait until extinguisher is created
|
||||
RemoveCompletedObjective(5);
|
||||
SetHighlight(mechanic_fabricator.Item, false);
|
||||
SetDoorAccess(mechanic_fourthDoor, mechanic_fourthDoorLight, true);
|
||||
|
||||
// Room 5
|
||||
do { yield return null; } while (!mechanic_fireSensor.MotionDetected);
|
||||
TriggerTutorialSegment(6, GameMain.Config.KeyBindText(InputType.Aim), GameMain.Config.KeyBindText(InputType.Shoot)); // Using the extinguisher
|
||||
TriggerTutorialSegment(6, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot)); // Using the extinguisher
|
||||
do { yield return null; } while (!mechanic_fire.Removed); // Wait until extinguished
|
||||
yield return new WaitForSeconds(3f, false);
|
||||
RemoveCompletedObjective(segments[6]);
|
||||
RemoveCompletedObjective(6);
|
||||
|
||||
if (mechanic.HasEquippedItem("extinguisher")) // do not trigger if dropped already
|
||||
if (mechanic.HasEquippedItem("extinguisher".ToIdentifier())) // do not trigger if dropped already
|
||||
{
|
||||
TriggerTutorialSegment(7);
|
||||
do
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "extinguisher", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "extinguisher".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
yield return null;
|
||||
} while (mechanic.HasEquippedItem("extinguisher"));
|
||||
RemoveCompletedObjective(segments[7]);
|
||||
} while (mechanic.HasEquippedItem("extinguisher".ToIdentifier()));
|
||||
RemoveCompletedObjective(7);
|
||||
}
|
||||
SetDoorAccess(mechanic_fifthDoor, mechanic_fifthDoorLight, true);
|
||||
|
||||
@@ -531,9 +605,9 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
yield return null;
|
||||
} while (!mechanic.HasEquippedItem("divingsuit", slotType: InvSlotType.OuterClothes));
|
||||
} while (!mechanic.HasEquippedItem("divingsuit".ToIdentifier(), slotType: InvSlotType.OuterClothes));
|
||||
SetHighlight(mechanic_divingSuitContainer.Item, false);
|
||||
RemoveCompletedObjective(segments[8]);
|
||||
RemoveCompletedObjective(8);
|
||||
SetDoorAccess(tutorial_mechanicFinalDoor, tutorial_mechanicFinalDoorLight, true);
|
||||
|
||||
// Room 7
|
||||
@@ -542,7 +616,7 @@ namespace Barotrauma.Tutorials
|
||||
mechanic.RemoveActiveObjectiveEntity(mechanic_brokenWall_2);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
|
||||
TriggerTutorialSegment(9, GameMain.Config.KeyBindText(InputType.Use)); // Repairing machinery (pump)
|
||||
TriggerTutorialSegment(9, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Use)); // Repairing machinery (pump)
|
||||
SetHighlight(mechanic_brokenPump.Item, true);
|
||||
mechanic_brokenPump.CanBeSelected = true;
|
||||
Repairable repairablePumpComponent = mechanic_brokenPump.Item.GetComponent<Repairable>();
|
||||
@@ -552,9 +626,9 @@ namespace Barotrauma.Tutorials
|
||||
yield return null;
|
||||
if (repairablePumpComponent.IsBelowRepairThreshold)
|
||||
{
|
||||
if (!mechanic.HasEquippedItem("wrench"))
|
||||
if (!mechanic.HasEquippedItem("wrench".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(mechanic.Inventory, "wrench", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(mechanic.Inventory, "wrench".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
}
|
||||
else if (IsSelectedItem(mechanic_brokenPump.Item) && repairablePumpComponent.CurrentFixer == null)
|
||||
{
|
||||
@@ -575,7 +649,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
} while (repairablePumpComponent.IsBelowRepairThreshold || mechanic_brokenPump.FlowPercentage >= 0 || !mechanic_brokenPump.IsActive);
|
||||
RemoveCompletedObjective(segments[9]);
|
||||
RemoveCompletedObjective(9);
|
||||
SetHighlight(mechanic_brokenPump.Item, false);
|
||||
do { yield return null; } while (mechanic_brokenhull_2.WaterPercentage > waterVolumeBeforeOpening);
|
||||
SetDoorAccess(tutorial_submarineDoor, tutorial_submarineDoorLight, true);
|
||||
@@ -599,7 +673,7 @@ namespace Barotrauma.Tutorials
|
||||
// Remove highlights when each individual machine is repaired
|
||||
do { CheckHighlights(repairablePumpComponent1, repairablePumpComponent2, repairableEngineComponent); yield return null; } while (repairablePumpComponent1.IsBelowRepairThreshold || repairablePumpComponent2.IsBelowRepairThreshold || repairableEngineComponent.IsBelowRepairThreshold);
|
||||
CheckHighlights(repairablePumpComponent1, repairablePumpComponent2, repairableEngineComponent);
|
||||
RemoveCompletedObjective(segments[10]);
|
||||
RemoveCompletedObjective(10);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Mechanic.Radio.Complete"), ChatMessageType.Radio, null);
|
||||
|
||||
// END TUTORIAL
|
||||
|
||||
+93
-41
@@ -72,62 +72,114 @@ namespace Barotrauma.Tutorials
|
||||
private PowerContainer officer_subSuperCapacitor_2;
|
||||
|
||||
// Variables
|
||||
private string radioSpeakerName;
|
||||
private LocalizedString radioSpeakerName;
|
||||
private Character officer;
|
||||
private float superCapacitorRechargeRate = 10;
|
||||
private Sprite officer_gunIcon;
|
||||
private Color officer_gunIconColor;
|
||||
|
||||
public OfficerTutorial(XElement element) : base(element)
|
||||
public OfficerTutorial() : base("tutorial.securityofficertraining".ToIdentifier(),
|
||||
new Segment(
|
||||
"Mechanic.Equipment".ToIdentifier(),
|
||||
"Mechanic.EquipmentObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Mechanic.EquipmentText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Officer.MeleeWeapon".ToIdentifier(),
|
||||
"Officer.MeleeWeaponObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Officer.MeleeWeaponText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Officer.Crawler".ToIdentifier(),
|
||||
"Officer.CrawlerObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Officer.CrawlerText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Officer.SomethingBig".ToIdentifier(),
|
||||
"Officer.SomethingBigObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Officer.SomethingBigText".ToIdentifier(), Width = 700, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_loaders.webm", TextTag = "Officer.SomethingBigText".ToIdentifier(), Width = 700, Height = 80 }),
|
||||
new Segment(
|
||||
"Officer.Hammerhead".ToIdentifier(),
|
||||
"Officer.HammerheadObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Officer.HammerheadText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Officer.RangedWeapon".ToIdentifier(),
|
||||
"Officer.RangedWeaponObjective".ToIdentifier(),
|
||||
TutorialContentType.ManualVideo,
|
||||
textContent: new Segment.Text { Tag = "Officer.RangedWeaponText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center },
|
||||
videoContent: new Segment.Video { File = "tutorial_ranged.webm", TextTag = "Officer.RangedWeaponText".ToIdentifier(), Width = 450, Height = 80 }),
|
||||
new Segment(
|
||||
"Officer.Mudraptor".ToIdentifier(),
|
||||
"Officer.MudraptorObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Officer.MudraptorText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }),
|
||||
new Segment(
|
||||
"Officer.ArmSubmarine".ToIdentifier(),
|
||||
"Officer.ArmSubmarineObjective".ToIdentifier(),
|
||||
TutorialContentType.TextOnly,
|
||||
textContent: new Segment.Text { Tag = "Officer.ArmSubmarineText".ToIdentifier(), Width = 450, Height = 80, Anchor = Anchor.Center }))
|
||||
{ }
|
||||
|
||||
protected override CharacterInfo GetCharacterInfo()
|
||||
{
|
||||
return new CharacterInfo(
|
||||
CharacterPrefab.HumanSpeciesName,
|
||||
jobOrJobPrefab: new Job(
|
||||
JobPrefab.Prefabs["medicaldoctor"], Rand.RandSync.Unsynced, 0,
|
||||
new Skill("medical".ToIdentifier(), 20),
|
||||
new Skill("weapons".ToIdentifier(), 70),
|
||||
new Skill("mechanical".ToIdentifier(), 20),
|
||||
new Skill("electrical".ToIdentifier(), 20),
|
||||
new Skill("helm".ToIdentifier(), 20)));
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
radioSpeakerName = TextManager.Get("Tutorial.Radio.Speaker");
|
||||
officer = Character.Controlled;
|
||||
|
||||
var handcuffs = FindOrGiveItem(officer, "handcuffs");
|
||||
var handcuffs = FindOrGiveItem(officer, "handcuffs".ToIdentifier());
|
||||
handcuffs.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(handcuffs);
|
||||
|
||||
var stunbaton = FindOrGiveItem(officer, "stunbaton");
|
||||
var stunbaton = FindOrGiveItem(officer, "stunbaton".ToIdentifier());
|
||||
stunbaton.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(stunbaton);
|
||||
|
||||
var smg = FindOrGiveItem(officer, "smg");
|
||||
var smg = FindOrGiveItem(officer, "smg".ToIdentifier());
|
||||
smg.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(smg);
|
||||
|
||||
var divingknife = FindOrGiveItem(officer, "divingknife");
|
||||
var divingknife = FindOrGiveItem(officer, "divingknife".ToIdentifier());
|
||||
divingknife.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(divingknife);
|
||||
|
||||
var steroids = FindOrGiveItem(officer, "steroids");
|
||||
var steroids = FindOrGiveItem(officer, "steroids".ToIdentifier());
|
||||
steroids.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(steroids);
|
||||
|
||||
var ballistichelmet =
|
||||
officer.Inventory.FindItemByIdentifier("ballistichelmet1") ??
|
||||
officer.Inventory.FindItemByIdentifier("ballistichelmet2") ??
|
||||
FindOrGiveItem(officer, "ballistichelmet3");
|
||||
officer.Inventory.FindItemByIdentifier("ballistichelmet1".ToIdentifier()) ??
|
||||
officer.Inventory.FindItemByIdentifier("ballistichelmet2".ToIdentifier()) ??
|
||||
FindOrGiveItem(officer, "ballistichelmet3".ToIdentifier());
|
||||
ballistichelmet.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(ballistichelmet);
|
||||
|
||||
var bodyarmor = FindOrGiveItem(officer, "bodyarmor");
|
||||
var bodyarmor = FindOrGiveItem(officer, "bodyarmor".ToIdentifier());
|
||||
bodyarmor.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(bodyarmor);
|
||||
|
||||
var gunOrder = Order.GetPrefab("operateweapons");
|
||||
var gunOrder = OrderPrefab.Prefabs["operateweapons"];
|
||||
officer_gunIcon = gunOrder.SymbolSprite;
|
||||
officer_gunIconColor = gunOrder.Color;
|
||||
|
||||
var bandage = FindOrGiveItem(officer, "antibleeding1");
|
||||
var bandage = FindOrGiveItem(officer, "antibleeding1".ToIdentifier());
|
||||
bandage.Unequip(officer);
|
||||
officer.Inventory.RemoveItem(bandage);
|
||||
FindOrGiveItem(officer, "antibleeding1");
|
||||
FindOrGiveItem(officer, "antibleeding1".ToIdentifier());
|
||||
|
||||
// Other tutorial items
|
||||
tutorial_mechanicFinalDoorLight = Item.ItemList.Find(i => i.HasTag("tutorial_mechanicfinaldoorlight")).GetComponent<LightComponent>();
|
||||
@@ -222,7 +274,7 @@ namespace Barotrauma.Tutorials
|
||||
do { yield return null; } while (!officer_equipmentObjectiveSensor.MotionDetected);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.Equipment"), ChatMessageType.Radio, null);
|
||||
yield return new WaitForSeconds(3f, false);
|
||||
//TriggerTutorialSegment(0, GameMain.Config.KeyBind(InputType.Select), GameMain.Config.KeyBind(InputType.Deselect)); // Retrieve equipment
|
||||
//TriggerTutorialSegment(0, GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Select], GameSettings.CurrentConfig.KeyMap.Bindings[InputType.Deselect]); // Retrieve equipment
|
||||
SetHighlight(officer_equipmentCabinet.Item, true);
|
||||
bool firstSlotRemoved = false;
|
||||
bool secondSlotRemoved = false;
|
||||
@@ -260,24 +312,24 @@ namespace Barotrauma.Tutorials
|
||||
//RemoveCompletedObjective(segments[0]);
|
||||
SetHighlight(officer_equipmentCabinet.Item, false);
|
||||
do { yield return null; } while (IsSelectedItem(officer_equipmentCabinet.Item));
|
||||
TriggerTutorialSegment(1, GameMain.Config.KeyBindText(InputType.Aim), GameMain.Config.KeyBindText(InputType.Shoot)); // Equip melee weapon & armor
|
||||
TriggerTutorialSegment(1, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot)); // Equip melee weapon & armor
|
||||
do
|
||||
{
|
||||
if (!officer.HasEquippedItem("stunbaton"))
|
||||
if (!officer.HasEquippedItem("stunbaton".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "stunbaton", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "stunbaton".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
if (!officer.HasEquippedItem("bodyarmor"))
|
||||
if (!officer.HasEquippedItem("bodyarmor".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "bodyarmor", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "bodyarmor".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
if (!officer.HasEquippedItem("ballistichelmet1"))
|
||||
if (!officer.HasEquippedItem("ballistichelmet1".ToIdentifier()))
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "ballistichelmet1", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "ballistichelmet1".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
} while (!officer.HasEquippedItem("stunbaton") || !officer.HasEquippedItem("bodyarmor") || !officer.HasEquippedItem("ballistichelmet1"));
|
||||
RemoveCompletedObjective(segments[1]);
|
||||
} while (!officer.HasEquippedItem("stunbaton".ToIdentifier()) || !officer.HasEquippedItem("bodyarmor".ToIdentifier()) || !officer.HasEquippedItem("ballistichelmet1".ToIdentifier()));
|
||||
RemoveCompletedObjective(1);
|
||||
SetDoorAccess(officer_firstDoor, officer_firstDoorLight, true);
|
||||
|
||||
// Room 3
|
||||
@@ -285,7 +337,7 @@ namespace Barotrauma.Tutorials
|
||||
TriggerTutorialSegment(2);
|
||||
officer_crawler = SpawnMonster("crawler", officer_crawlerSpawnPos);
|
||||
do { yield return null; } while (!officer_crawler.IsDead);
|
||||
RemoveCompletedObjective(segments[2]);
|
||||
RemoveCompletedObjective(2);
|
||||
Heal(officer);
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.CrawlerDead"), ChatMessageType.Radio, null);
|
||||
@@ -305,7 +357,7 @@ namespace Barotrauma.Tutorials
|
||||
SetHighlight(officer_ammoShelf_2.Item, officer_coilgunLoader.Item.ExternalHighlight );
|
||||
if (IsSelectedItem(officer_coilgunLoader.Item))
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "coilgunammobox", highlightColor, .5f, .5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "coilgunammobox".ToIdentifier(), highlightColor, .5f, .5f, 0f);
|
||||
}
|
||||
yield return null;
|
||||
} while (officer_coilgunLoader.Inventory.GetItemAt(0) == null || officer_superCapacitor.RechargeSpeed < superCapacitorRechargeRate || officer_coilgunLoader.Inventory.GetItemAt(0).Condition == 0);
|
||||
@@ -313,9 +365,9 @@ namespace Barotrauma.Tutorials
|
||||
SetHighlight(officer_superCapacitor.Item, false);
|
||||
SetHighlight(officer_ammoShelf_1.Item, false);
|
||||
SetHighlight(officer_ammoShelf_2.Item, false);
|
||||
RemoveCompletedObjective(segments[3]);
|
||||
RemoveCompletedObjective(3);
|
||||
yield return new WaitForSeconds(2f, false);
|
||||
TriggerTutorialSegment(4, GameMain.Config.KeyBindText(InputType.Select), GameMain.Config.KeyBindText(InputType.Shoot), GameMain.Config.KeyBindText(InputType.Deselect)); // Kill hammerhead
|
||||
TriggerTutorialSegment(4, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Select), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Deselect)); // Kill hammerhead
|
||||
officer_hammerhead = SpawnMonster("hammerhead", officer_hammerheadSpawnPos);
|
||||
officer_hammerhead.Params.AI.AvoidAbyss = false;
|
||||
officer_hammerhead.Params.AI.StayInAbyss = false;
|
||||
@@ -348,7 +400,7 @@ namespace Barotrauma.Tutorials
|
||||
while(!officer_hammerhead.IsDead);
|
||||
Heal(officer);
|
||||
SetHighlight(officer_coilgunPeriscope, false);
|
||||
RemoveCompletedObjective(segments[4]);
|
||||
RemoveCompletedObjective(4);
|
||||
yield return new WaitForSeconds(1f, false);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.HammerheadDead"), ChatMessageType.Radio, null);
|
||||
SetDoorAccess(officer_thirdDoor, officer_thirdDoorLight, true);
|
||||
@@ -357,16 +409,16 @@ namespace Barotrauma.Tutorials
|
||||
//do { yield return null; } while (!officer_rangedWeaponSensor.MotionDetected);
|
||||
do { yield return null; } while (!officer_thirdDoor.IsOpen);
|
||||
yield return new WaitForSeconds(3f, false);
|
||||
TriggerTutorialSegment(5, GameMain.Config.KeyBindText(InputType.Aim), GameMain.Config.KeyBindText(InputType.Shoot)); // Ranged weapons
|
||||
TriggerTutorialSegment(5, GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Aim), GameSettings.CurrentConfig.KeyMap.KeyBindText(InputType.Shoot)); // Ranged weapons
|
||||
SetHighlight(officer_rangedWeaponHolder.Item, true);
|
||||
do { yield return null; } while (!officer_rangedWeaponHolder.Inventory.IsEmpty()); // Wait until looted
|
||||
SetHighlight(officer_rangedWeaponHolder.Item, false);
|
||||
do
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "shotgun", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "shotgun".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
yield return null;
|
||||
} while (!officer.HasEquippedItem("shotgun")); // Wait until equipped
|
||||
ItemContainer shotGunChamber = officer.Inventory.FindItemByIdentifier("shotgun").GetComponent<ItemContainer>();
|
||||
} while (!officer.HasEquippedItem("shotgun".ToIdentifier())); // Wait until equipped
|
||||
ItemContainer shotGunChamber = officer.Inventory.FindItemByIdentifier("shotgun".ToIdentifier()).GetComponent<ItemContainer>();
|
||||
SetHighlight(officer_rangedWeaponCabinet.Item, true);
|
||||
do
|
||||
{
|
||||
@@ -392,13 +444,13 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
|
||||
if (officer.Inventory.FindItemByIdentifier("shotgunshell") != null || (IsSelectedItem(officer_rangedWeaponCabinet.Item) && officer_rangedWeaponCabinet.Inventory.FindItemByIdentifier("shotgunshell") != null))
|
||||
if (officer.Inventory.FindItemByIdentifier("shotgunshell".ToIdentifier()) != null || (IsSelectedItem(officer_rangedWeaponCabinet.Item) && officer_rangedWeaponCabinet.Inventory.FindItemByIdentifier("shotgunshell".ToIdentifier()) != null))
|
||||
{
|
||||
HighlightInventorySlot(officer.Inventory, "shotgun", highlightColor, 0.5f, 0.5f, 0f);
|
||||
HighlightInventorySlot(officer.Inventory, "shotgun".ToIdentifier(), highlightColor, 0.5f, 0.5f, 0f);
|
||||
}
|
||||
yield return null;
|
||||
} while (!shotGunChamber.Inventory.IsFull(takeStacksIntoAccount: true)); // Wait until all six harpoons loaded
|
||||
RemoveCompletedObjective(segments[5]);
|
||||
RemoveCompletedObjective(5);
|
||||
SetHighlight(officer_rangedWeaponCabinet.Item, false);
|
||||
SetDoorAccess(officer_fourthDoor, officer_fourthDoorLight, true);
|
||||
|
||||
@@ -408,7 +460,7 @@ namespace Barotrauma.Tutorials
|
||||
officer_mudraptor = SpawnMonster("mudraptor", officer_mudraptorSpawnPos);
|
||||
do { yield return null; } while (!officer_mudraptor.IsDead);
|
||||
Heal(officer);
|
||||
RemoveCompletedObjective(segments[6]);
|
||||
RemoveCompletedObjective(6);
|
||||
SetDoorAccess(tutorial_securityFinalDoor, tutorial_securityFinalDoorLight, true);
|
||||
|
||||
// Submarine
|
||||
@@ -459,7 +511,7 @@ namespace Barotrauma.Tutorials
|
||||
officer.RemoveActiveObjectiveEntity(officer_subSuperCapacitor_2.Item);
|
||||
officer.RemoveActiveObjectiveEntity(officer_subAmmoBox_1);
|
||||
officer.RemoveActiveObjectiveEntity(officer_subAmmoBox_2);
|
||||
RemoveCompletedObjective(segments[7]);
|
||||
RemoveCompletedObjective(7);
|
||||
GameMain.GameSession?.CrewManager.AddSinglePlayerChatMessage(radioSpeakerName, TextManager.Get("Officer.Radio.Complete"), ChatMessageType.Radio, null);
|
||||
|
||||
yield return new WaitForSeconds(4f, false);
|
||||
|
||||
+41
-54
@@ -8,18 +8,21 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
class ScenarioTutorial : Tutorial
|
||||
abstract class ScenarioTutorial : Tutorial
|
||||
{
|
||||
private CoroutineHandle tutorialCoroutine;
|
||||
|
||||
private Character character;
|
||||
private string spawnSub;
|
||||
private SpawnType spawnPointType;
|
||||
private string submarinePath;
|
||||
private string startOutpostPath;
|
||||
private string endOutpostPath;
|
||||
private string levelSeed;
|
||||
private string levelParams;
|
||||
|
||||
private const string submarinePath = "Content/Tutorials/Dugong_Tutorial.sub";
|
||||
private const string startOutpostPath = "Content/Tutorials/TutorialOutpost.sub";
|
||||
//private const string endOutpostPath = "";
|
||||
|
||||
private const string levelSeed = "nLoZLLtza";
|
||||
private const string levelParams = "ColdCavernsTutorial";
|
||||
|
||||
//private const string spawnSub = "startoutpost";
|
||||
private const SpawnType spawnPointType = SpawnType.Human;
|
||||
|
||||
private SubmarineInfo startOutpost = null;
|
||||
private SubmarineInfo endOutpost = null;
|
||||
@@ -31,34 +34,18 @@ namespace Barotrauma.Tutorials
|
||||
protected Color highlightColor = Color.OrangeRed;
|
||||
protected Color uiHighlightColor = new Color(150, 50, 0);
|
||||
protected Color buttonHighlightColor = new Color(255, 100, 0);
|
||||
protected Color inaccessibleColor = GUI.Style.Red;
|
||||
protected Color accessibleColor = GUI.Style.Green;
|
||||
protected Color inaccessibleColor = GUIStyle.Red;
|
||||
protected Color accessibleColor = GUIStyle.Green;
|
||||
|
||||
public ScenarioTutorial(XElement element) : base(element)
|
||||
{
|
||||
submarinePath = element.GetAttributeString("submarinepath", "");
|
||||
startOutpostPath = element.GetAttributeString("startoutpostpath", "");
|
||||
endOutpostPath = element.GetAttributeString("endoutpostpath", "");
|
||||
protected ScenarioTutorial(Identifier identifier, params Segment[] segments) : base(identifier, segments) { }
|
||||
|
||||
levelSeed = element.GetAttributeString("levelseed", "tuto");
|
||||
levelParams = element.GetAttributeString("levelparams", "");
|
||||
|
||||
spawnSub = element.GetAttributeString("spawnsub", "");
|
||||
Enum.TryParse(element.GetAttributeString("spawnpointtype", "Human"), true, out spawnPointType);
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
currentTutorialCompleted = false;
|
||||
GameMain.Instance.ShowLoading(Loading());
|
||||
}
|
||||
|
||||
private IEnumerable<CoroutineStatus> Loading()
|
||||
protected abstract void Initialize();
|
||||
|
||||
protected override IEnumerable<CoroutineStatus> Loading()
|
||||
{
|
||||
SubmarineInfo subInfo = new SubmarineInfo(submarinePath);
|
||||
|
||||
LevelGenerationParams generationParams = LevelGenerationParams.LevelParams.Find(p => p.Identifier.Equals(levelParams, StringComparison.OrdinalIgnoreCase));
|
||||
LevelGenerationParams generationParams = LevelGenerationParams.LevelParams.Find(p => p.Identifier == levelParams);
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
@@ -68,18 +55,18 @@ namespace Barotrauma.Tutorials
|
||||
if (generationParams != null)
|
||||
{
|
||||
Biome biome =
|
||||
LevelGenerationParams.GetBiomes().FirstOrDefault(b => generationParams.AllowedBiomes.Contains(b)) ??
|
||||
LevelGenerationParams.GetBiomes().First();
|
||||
Biome.Prefabs.FirstOrDefault(b => generationParams.AllowedBiomeIdentifiers.Contains(b.Identifier)) ??
|
||||
Biome.Prefabs.First();
|
||||
|
||||
if (!string.IsNullOrEmpty(startOutpostPath))
|
||||
{
|
||||
startOutpost = new SubmarineInfo(startOutpostPath);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(endOutpostPath))
|
||||
/*if (!string.IsNullOrEmpty(endOutpostPath))
|
||||
{
|
||||
endOutpost = new SubmarineInfo(endOutpostPath);
|
||||
}
|
||||
}*/
|
||||
|
||||
LevelData tutorialLevel = new LevelData(levelSeed, 0, 0, generationParams, biome);
|
||||
GameMain.GameSession.StartRound(tutorialLevel, startOutpost: startOutpost, endOutpost: endOutpost);
|
||||
@@ -93,12 +80,6 @@ namespace Barotrauma.Tutorials
|
||||
GameMain.GameSession.EventManager.Enabled = false;
|
||||
GameMain.GameScreen.Select();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
|
||||
Submarine.MainSub.GodMode = true;
|
||||
foreach (Structure wall in Structure.WallList)
|
||||
@@ -109,16 +90,15 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
|
||||
CharacterInfo charInfo = configElement.Element("Character") == null ?
|
||||
new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: JobPrefab.Get("engineer")) :
|
||||
new CharacterInfo(configElement.Element("Character"));
|
||||
CharacterInfo charInfo = GetCharacterInfo();
|
||||
|
||||
WayPoint wayPoint = GetSpawnPoint(charInfo);
|
||||
|
||||
if (wayPoint == null)
|
||||
{
|
||||
DebugConsole.ThrowError("A waypoint with the spawntype \"" + spawnPointType + "\" is required for the tutorial event");
|
||||
return;
|
||||
yield return CoroutineStatus.Failure;
|
||||
yield break;
|
||||
}
|
||||
|
||||
character = Character.Create(charInfo, wayPoint.WorldPosition, "", isRemotePlayer: false, hasAi: false);
|
||||
@@ -126,11 +106,12 @@ namespace Barotrauma.Tutorials
|
||||
Character.Controlled = character;
|
||||
character.GiveJobItems(null);
|
||||
|
||||
var idCard = character.Inventory.FindItemByIdentifier("idcard");
|
||||
var idCard = character.Inventory.FindItemByIdentifier("idcard".ToIdentifier());
|
||||
if (idCard == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Item prefab \"ID Card\" not found!");
|
||||
return;
|
||||
yield return CoroutineStatus.Failure;
|
||||
yield break;
|
||||
}
|
||||
idCard.AddTag("com");
|
||||
idCard.AddTag("eng");
|
||||
@@ -145,8 +126,14 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
|
||||
tutorialCoroutine = CoroutineManager.StartCoroutine(UpdateState());
|
||||
|
||||
Initialize();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
protected abstract CharacterInfo GetCharacterInfo();
|
||||
|
||||
public override void AddToGUIUpdateList()
|
||||
{
|
||||
if (!currentTutorialCompleted)
|
||||
@@ -157,7 +144,7 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
private WayPoint GetSpawnPoint(CharacterInfo charInfo)
|
||||
{
|
||||
Submarine spawnSub = null;
|
||||
/*Submarine spawnSub = null;
|
||||
|
||||
if (this.spawnSub != string.Empty)
|
||||
{
|
||||
@@ -175,15 +162,15 @@ namespace Barotrauma.Tutorials
|
||||
spawnSub = Submarine.MainSub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}*/
|
||||
Submarine spawnSub = Level.Loaded.StartOutpost;
|
||||
return WayPoint.GetRandom(spawnPointType, charInfo.Job?.Prefab, spawnSub);
|
||||
}
|
||||
|
||||
protected bool HasOrder(Character character, string identifier, string option = null)
|
||||
{
|
||||
var currentOrderInfo = character.GetCurrentOrderWithTopPriority();
|
||||
if (currentOrderInfo?.Order?.Identifier == identifier)
|
||||
if (currentOrderInfo?.Identifier == identifier)
|
||||
{
|
||||
if (option == null)
|
||||
{
|
||||
@@ -191,7 +178,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
else
|
||||
{
|
||||
return currentOrderInfo?.OrderOption == option;
|
||||
return currentOrderInfo?.Option == option;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +254,7 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
yield return new WaitForSeconds(3.0f);
|
||||
|
||||
var messageBox = new GUIMessageBox(TextManager.Get("Tutorial.TryAgainHeader"), TextManager.Get("Tutorial.TryAgain"), new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
var messageBox = new GUIMessageBox(TextManager.Get("Tutorial.TryAgainHeader"), TextManager.Get("Tutorial.TryAgain"), new LocalizedString[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
|
||||
messageBox.Buttons[0].OnClicked += Restart;
|
||||
messageBox.Buttons[0].OnClicked += messageBox.Close;
|
||||
@@ -303,7 +290,7 @@ namespace Barotrauma.Tutorials
|
||||
character.SetStun(0.0f, true);
|
||||
}
|
||||
|
||||
protected Item FindOrGiveItem(Character character, string identifier)
|
||||
protected Item FindOrGiveItem(Character character, Identifier identifier)
|
||||
{
|
||||
var item = character.Inventory.FindItemByIdentifier(identifier);
|
||||
if (item != null && !item.Removed) { return item; }
|
||||
|
||||
+159
-232
@@ -7,189 +7,128 @@ using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Extensions;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma.Tutorials
|
||||
{
|
||||
enum TutorialContentType { None = 0, Video = 1, ManualVideo = 2, TextOnly = 3 };
|
||||
|
||||
/// <summary>
|
||||
/// If you're seeing this and are currently working on improving the tutorials, consider
|
||||
/// deleting this class and all that derive from it, and starting from scratch.
|
||||
/// </summary>
|
||||
abstract class Tutorial
|
||||
{
|
||||
#region Tutorial variables
|
||||
public static bool Initialized = false;
|
||||
public static bool ContentRunning = false;
|
||||
public static List<Tutorial> Tutorials;
|
||||
#region Constants
|
||||
public const string PlayableContentPath = "Content/Tutorials/TutorialVideos/";
|
||||
#endregion
|
||||
|
||||
#region Tutorial variables
|
||||
public static ImmutableHashSet<Type> Types;
|
||||
static Tutorial()
|
||||
{
|
||||
Types = ReflectionUtils.GetDerivedNonAbstract<Tutorial>()
|
||||
.ToImmutableHashSet();
|
||||
}
|
||||
|
||||
public readonly Identifier Identifier;
|
||||
|
||||
public LocalizedString DisplayName { get; }
|
||||
|
||||
public bool ContentRunning { get; protected set; }
|
||||
|
||||
protected bool started = false;
|
||||
protected GUIComponent infoBox;
|
||||
private Action infoBoxClosedCallback;
|
||||
protected XElement configElement;
|
||||
|
||||
protected VideoPlayer videoPlayer;
|
||||
protected enum TutorialContentTypes { None = 0, Video = 1, ManualVideo = 2, TextOnly = 3 };
|
||||
protected string playableContentPath;
|
||||
protected Point screenResolution;
|
||||
protected WindowMode windowMode;
|
||||
protected float prevUIScale;
|
||||
|
||||
private GUIFrame holderFrame, objectiveFrame;
|
||||
private List<TutorialSegment> activeObjectives = new List<TutorialSegment>();
|
||||
private string objectiveTranslated;
|
||||
private readonly List<Index> activeObjectives;
|
||||
private readonly LocalizedString objectiveTranslated;
|
||||
|
||||
protected TutorialSegment activeContentSegment;
|
||||
protected List<TutorialSegment> segments;
|
||||
protected readonly ImmutableArray<Segment> segments;
|
||||
protected Index activeContentSegmentIndex;
|
||||
protected Segment activeContentSegment => segments[activeContentSegmentIndex];
|
||||
|
||||
protected class TutorialSegment
|
||||
protected class Segment
|
||||
{
|
||||
public string Id;
|
||||
public string Objective;
|
||||
public TutorialContentTypes ContentType;
|
||||
public XElement TextContent;
|
||||
public XElement VideoContent;
|
||||
public struct Text
|
||||
{
|
||||
public Identifier Tag;
|
||||
public int Width;
|
||||
public int Height;
|
||||
public Anchor Anchor;
|
||||
}
|
||||
|
||||
public struct Video
|
||||
{
|
||||
public string File;
|
||||
public Identifier TextTag;
|
||||
public int Width;
|
||||
public int Height;
|
||||
}
|
||||
|
||||
public bool IsTriggered;
|
||||
public GUIButton ReplayButton;
|
||||
public GUITextBlock LinkedTitle, LinkedText;
|
||||
public object[] Args;
|
||||
public LocalizedString Objective;
|
||||
|
||||
public TutorialSegment(XElement config)
|
||||
public readonly Identifier Id;
|
||||
public readonly Text? TextContent;
|
||||
public readonly Video? VideoContent;
|
||||
public readonly TutorialContentType ContentType;
|
||||
|
||||
public Segment(Identifier id, Identifier objectiveTextTag, TutorialContentType contentType, Text? textContent = null, Video? videoContent = null)
|
||||
{
|
||||
Id = config.GetAttributeString("id", "Missing ID");
|
||||
Objective = TextManager.Get(config.GetAttributeString("objective", string.Empty), true);
|
||||
Enum.TryParse(config.GetAttributeString("contenttype", "None"), true, out ContentType);
|
||||
IsTriggered = config.GetAttributeBool("istriggered", false);
|
||||
Id = id;
|
||||
Objective = TextManager.ParseInputTypes(TextManager.Get(objectiveTextTag));
|
||||
ContentType = contentType;
|
||||
TextContent = textContent;
|
||||
VideoContent = videoContent;
|
||||
|
||||
switch (ContentType)
|
||||
{
|
||||
case TutorialContentTypes.None:
|
||||
break;
|
||||
case TutorialContentTypes.Video:
|
||||
case TutorialContentTypes.ManualVideo:
|
||||
VideoContent = config.Element("Video");
|
||||
TextContent = config.Element("Text");
|
||||
break;
|
||||
case TutorialContentTypes.TextOnly:
|
||||
TextContent = config.Element("Text");
|
||||
break;
|
||||
}
|
||||
IsTriggered = false;
|
||||
}
|
||||
}
|
||||
|
||||
public string Identifier
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public string DisplayName
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
private bool completed;
|
||||
public bool Completed
|
||||
{
|
||||
get { return completed; }
|
||||
protected set
|
||||
{
|
||||
if (completed == value) return;
|
||||
if (completed == value) { return; }
|
||||
completed = value;
|
||||
GameMain.Config.SaveNewPlayerConfig();
|
||||
if (value)
|
||||
{
|
||||
CompletedTutorials.Instance.Add(Identifier);
|
||||
}
|
||||
GameSettings.SaveCurrentConfig();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Tutorial Controls
|
||||
public static void Init()
|
||||
protected Tutorial(Identifier identifier, params Segment[] segments)
|
||||
{
|
||||
Tutorials = new List<Tutorial>();
|
||||
foreach (ContentFile file in GameMain.Instance.GetFilesOfType(ContentType.Tutorials))
|
||||
{
|
||||
XDocument doc = XMLExtensions.TryLoadXml(file.Path);
|
||||
if (doc?.Root == null) continue;
|
||||
|
||||
foreach (XElement element in doc.Root.Elements())
|
||||
{
|
||||
Tutorial newTutorial = Load(element);
|
||||
if (newTutorial != null) Tutorials.Add(newTutorial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Tutorial Load(XElement element)
|
||||
{
|
||||
Type t;
|
||||
string type = element.Name.ToString().ToLowerInvariant();
|
||||
try
|
||||
{
|
||||
// Get the type of a specified class.
|
||||
t = Type.GetType("Barotrauma.Tutorials." + type + "", false, true);
|
||||
if (t == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find tutorial type \"" + type + "\"");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find tutorial type \"" + type + "\"", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
ConstructorInfo constructor;
|
||||
try
|
||||
{
|
||||
if (!t.IsSubclassOf(typeof(Tutorial))) return null;
|
||||
constructor = t.GetConstructor(new Type[] { typeof(XElement) });
|
||||
if (constructor == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find the constructor of tutorial type \"" + type + "\"");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Could not find the constructor of tutorial type \"" + type + "\"", e);
|
||||
return null;
|
||||
}
|
||||
Tutorial tutorial = null;
|
||||
try
|
||||
{
|
||||
object component = constructor.Invoke(new object[] { element });
|
||||
tutorial = (Tutorial)component;
|
||||
}
|
||||
catch (TargetInvocationException e)
|
||||
{
|
||||
DebugConsole.ThrowError("Error while loading tutorial of the type " + t + ".", e.InnerException);
|
||||
}
|
||||
|
||||
return tutorial;
|
||||
}
|
||||
|
||||
public Tutorial(XElement element)
|
||||
{
|
||||
configElement = element;
|
||||
Identifier = element.GetAttributeString("identifier", "unknown");
|
||||
Identifier = identifier;
|
||||
this.segments = segments.ToImmutableArray();
|
||||
DisplayName = TextManager.Get(Identifier);
|
||||
completed = GameMain.Config.CompletedTutorialNames.Contains(Identifier);
|
||||
playableContentPath = element.GetAttributeString("playablecontentpath", "");
|
||||
|
||||
segments = new List<TutorialSegment>();
|
||||
|
||||
foreach (var segment in element.Elements("Segment"))
|
||||
{
|
||||
segments.Add(new TutorialSegment(segment));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Initialize()
|
||||
{
|
||||
if (Initialized) return;
|
||||
Initialized = true;
|
||||
videoPlayer = new VideoPlayer();
|
||||
}
|
||||
|
||||
public virtual void Start()
|
||||
{
|
||||
activeObjectives.Clear();
|
||||
activeObjectives = new List<Index>();
|
||||
objectiveTranslated = TextManager.Get("Tutorial.Objective");
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<CoroutineStatus> Loading();
|
||||
|
||||
public void Start()
|
||||
{
|
||||
videoPlayer = new VideoPlayer();
|
||||
GameMain.Instance.ShowLoading(Loading());
|
||||
|
||||
activeObjectives.Clear();
|
||||
CreateObjectiveFrame();
|
||||
|
||||
// Setup doors: Clear all requirements, unless the door is setup as locked.
|
||||
@@ -208,7 +147,7 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
public virtual void AddToGUIUpdateList()
|
||||
{
|
||||
if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y || prevUIScale != GUI.Scale || GameMain.Config.WindowMode != windowMode)
|
||||
if (GameMain.GraphicsWidth != screenResolution.X || GameMain.GraphicsHeight != screenResolution.Y || prevUIScale != GUI.Scale || GameSettings.CurrentConfig.Graphics.DisplayMode != windowMode)
|
||||
{
|
||||
CreateObjectiveFrame();
|
||||
}
|
||||
@@ -255,74 +194,69 @@ namespace Barotrauma.Tutorials
|
||||
protected bool Restart(GUIButton button, object obj)
|
||||
{
|
||||
GUI.PreventPauseMenuToggle = false;
|
||||
TutorialMode.StartTutorial(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected virtual void TriggerTutorialSegment(int index, params object[] args)
|
||||
protected virtual void TriggerTutorialSegment(Index index, params object[] args)
|
||||
{
|
||||
Inventory.DraggingItems.Clear();
|
||||
ContentRunning = true;
|
||||
activeContentSegment = segments[index];
|
||||
activeContentSegmentIndex = index;
|
||||
segments[index].Args = args;
|
||||
|
||||
string tutorialText = TextManager.GetFormatted(activeContentSegment.TextContent.GetAttributeString("tag", ""), true, args);
|
||||
LocalizedString tutorialText = TextManager.GetFormatted(segments[index].TextContent.Value.Tag, args);
|
||||
tutorialText = TextManager.ParseInputTypes(tutorialText);
|
||||
string objectiveText = string.Empty;
|
||||
LocalizedString objectiveText = string.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(activeContentSegment.Objective))
|
||||
if (!segments[index].Objective.IsNullOrEmpty())
|
||||
{
|
||||
if (args.Length == 0)
|
||||
{
|
||||
objectiveText = activeContentSegment.Objective;
|
||||
objectiveText = segments[index].Objective;
|
||||
}
|
||||
else
|
||||
{
|
||||
objectiveText = string.Format(activeContentSegment.Objective, args);
|
||||
objectiveText = TextManager.GetFormatted(segments[index].Objective, args);
|
||||
}
|
||||
objectiveText = TextManager.ParseInputTypes(objectiveText);
|
||||
activeContentSegment.Objective = objectiveText;
|
||||
segments[index].Objective = objectiveText;
|
||||
}
|
||||
else
|
||||
{
|
||||
activeContentSegment.IsTriggered = true; // Complete at this stage only if no related objective
|
||||
segments[index].IsTriggered = true; // Complete at this stage only if no related objective
|
||||
}
|
||||
|
||||
|
||||
switch (activeContentSegment.ContentType)
|
||||
switch (segments[index].ContentType)
|
||||
{
|
||||
case TutorialContentTypes.None:
|
||||
case TutorialContentType.None:
|
||||
break;
|
||||
case TutorialContentTypes.Video:
|
||||
case TutorialContentType.Video:
|
||||
infoBox = CreateInfoFrame(TextManager.Get(activeContentSegment.Id), tutorialText,
|
||||
activeContentSegment.TextContent.GetAttributeInt("width", 300),
|
||||
activeContentSegment.TextContent.GetAttributeInt("height", 80),
|
||||
activeContentSegment.TextContent.GetAttributeString("anchor", "Center"), true, () => LoadVideo(activeContentSegment));
|
||||
activeContentSegment.TextContent.Value.Width,
|
||||
activeContentSegment.TextContent.Value.Height,
|
||||
activeContentSegment.TextContent.Value.Anchor, true, () => LoadVideo(activeContentSegment));
|
||||
break;
|
||||
case TutorialContentTypes.ManualVideo:
|
||||
case TutorialContentType.ManualVideo:
|
||||
infoBox = CreateInfoFrame(TextManager.Get(activeContentSegment.Id), tutorialText,
|
||||
activeContentSegment.TextContent.GetAttributeInt("width", 300),
|
||||
activeContentSegment.TextContent.GetAttributeInt("height", 80),
|
||||
activeContentSegment.TextContent.GetAttributeString("anchor", "Center"), true, StopCurrentContentSegment, () => LoadVideo(activeContentSegment));
|
||||
activeContentSegment.TextContent.Value.Width,
|
||||
activeContentSegment.TextContent.Value.Height,
|
||||
activeContentSegment.TextContent.Value.Anchor, true, StopCurrentContentSegment, () => LoadVideo(activeContentSegment));
|
||||
break;
|
||||
case TutorialContentTypes.TextOnly:
|
||||
case TutorialContentType.TextOnly:
|
||||
infoBox = CreateInfoFrame(TextManager.Get(activeContentSegment.Id), tutorialText,
|
||||
activeContentSegment.TextContent.GetAttributeInt("width", 300),
|
||||
activeContentSegment.TextContent.GetAttributeInt("height", 80),
|
||||
activeContentSegment.TextContent.GetAttributeString("anchor", "Center"), true, StopCurrentContentSegment);
|
||||
activeContentSegment.TextContent.Value.Width,
|
||||
activeContentSegment.TextContent.Value.Height,
|
||||
activeContentSegment.TextContent.Value.Anchor, true, StopCurrentContentSegment);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Stop()
|
||||
{
|
||||
started = ContentRunning = Initialized = false;
|
||||
ContentRunning = false;
|
||||
infoBox = null;
|
||||
if (videoPlayer != null)
|
||||
{
|
||||
videoPlayer.Remove();
|
||||
videoPlayer = null;
|
||||
}
|
||||
videoPlayer.Remove();
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -334,50 +268,51 @@ namespace Barotrauma.Tutorials
|
||||
|
||||
for (int i = 0; i < activeObjectives.Count; i++)
|
||||
{
|
||||
CreateObjectiveGUI(activeObjectives[i], i, activeObjectives[i].ContentType);
|
||||
CreateObjectiveGUI(activeObjectives[i], i, segments[activeObjectives[i]].ContentType);
|
||||
}
|
||||
|
||||
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
|
||||
windowMode = GameMain.Config.WindowMode;
|
||||
windowMode = GameSettings.CurrentConfig.Graphics.DisplayMode;
|
||||
prevUIScale = GUI.Scale;
|
||||
}
|
||||
|
||||
protected void StopCurrentContentSegment()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(activeContentSegment.Objective))
|
||||
if (!activeContentSegment.Objective.IsNullOrEmpty())
|
||||
{
|
||||
AddNewObjective(activeContentSegment, activeContentSegment.ContentType);
|
||||
AddNewObjective(activeContentSegmentIndex, activeContentSegment.ContentType);
|
||||
}
|
||||
|
||||
activeContentSegment = null;
|
||||
ContentRunning = false;
|
||||
activeContentSegmentIndex = Index.End;
|
||||
}
|
||||
|
||||
protected virtual void CheckActiveObjectives(TutorialSegment objective, float deltaTime)
|
||||
protected virtual void CheckActiveObjectives(Index objective, float deltaTime)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected bool HasObjective(TutorialSegment segment)
|
||||
protected bool HasObjective(Index segment)
|
||||
{
|
||||
return activeObjectives.Contains(segment);
|
||||
}
|
||||
|
||||
protected void AddNewObjective(TutorialSegment segment, TutorialContentTypes type)
|
||||
protected void AddNewObjective(Index segment, TutorialContentType type)
|
||||
{
|
||||
activeObjectives.Add(segment);
|
||||
CreateObjectiveGUI(segment, activeObjectives.Count - 1, type);
|
||||
}
|
||||
|
||||
private void CreateObjectiveGUI(TutorialSegment segment, int index, TutorialContentTypes type)
|
||||
private void CreateObjectiveGUI(Index segmentIndex, int index, TutorialContentType type)
|
||||
{
|
||||
string objectiveText = TextManager.ParseInputTypes(segment.Objective);
|
||||
Point replayButtonSize = new Point((int)(GUI.LargeFont.MeasureString(objectiveText).X), (int)(GUI.LargeFont.MeasureString(objectiveText).Y * 1.45f));
|
||||
var segment = segments[segmentIndex];
|
||||
LocalizedString objectiveText = TextManager.ParseInputTypes(segment.Objective);
|
||||
Point replayButtonSize = new Point((int)(GUIStyle.LargeFont.MeasureString(objectiveText).X), (int)(GUIStyle.LargeFont.MeasureString(objectiveText).Y * 1.45f));
|
||||
|
||||
segment.ReplayButton = new GUIButton(new RectTransform(replayButtonSize, objectiveFrame.RectTransform, Anchor.TopLeft, Pivot.TopLeft) { AbsoluteOffset = new Point(0, (replayButtonSize.Y + (int)(20f * GUI.Scale)) * index) }, style: null);
|
||||
segment.ReplayButton.OnClicked += (GUIButton btn, object userdata) =>
|
||||
{
|
||||
if (type == TutorialContentTypes.Video)
|
||||
if (type == TutorialContentType.Video)
|
||||
{
|
||||
ReplaySegmentVideo(segment);
|
||||
}
|
||||
@@ -388,23 +323,23 @@ namespace Barotrauma.Tutorials
|
||||
return true;
|
||||
};
|
||||
|
||||
string objectiveTitleText = TextManager.ParseInputTypes(objectiveTranslated);
|
||||
int yOffset = (int)((GUI.SubHeadingFont.MeasureString(objectiveTitleText).Y + 5));
|
||||
segment.LinkedTitle = new GUITextBlock(new RectTransform(new Point((int)GUI.SubHeadingFont.MeasureString(objectiveTitleText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.BottomLeft) /*{ AbsoluteOffset = new Point((int)(-10 * GUI.Scale), 0) }*/,
|
||||
objectiveTitleText, textColor: Color.White, font: GUI.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
||||
LocalizedString objectiveTitleText = TextManager.ParseInputTypes(objectiveTranslated);
|
||||
int yOffset = (int)((GUIStyle.SubHeadingFont.MeasureString(objectiveTitleText).Y + 5));
|
||||
segment.LinkedTitle = new GUITextBlock(new RectTransform(new Point((int)GUIStyle.SubHeadingFont.MeasureString(objectiveTitleText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.BottomLeft) /*{ AbsoluteOffset = new Point((int)(-10 * GUI.Scale), 0) }*/,
|
||||
objectiveTitleText, textColor: Color.White, font: GUIStyle.SubHeadingFont, textAlignment: Alignment.CenterLeft)
|
||||
{
|
||||
ForceUpperCase = true
|
||||
ForceUpperCase = ForceUpperCase.Yes
|
||||
};
|
||||
|
||||
segment.LinkedText = new GUITextBlock(new RectTransform(new Point((int)GUI.LargeFont.MeasureString(objectiveText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.TopLeft) /*{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), 0) }*/,
|
||||
objectiveText, textColor: new Color(4, 180, 108), font: GUI.LargeFont, textAlignment: Alignment.CenterLeft);
|
||||
segment.LinkedText = new GUITextBlock(new RectTransform(new Point((int)GUIStyle.LargeFont.MeasureString(objectiveText).X, yOffset), segment.ReplayButton.RectTransform, Anchor.CenterLeft, Pivot.TopLeft) /*{ AbsoluteOffset = new Point((int)(10 * GUI.Scale), 0) }*/,
|
||||
objectiveText, textColor: new Color(4, 180, 108), font: GUIStyle.LargeFont, textAlignment: Alignment.CenterLeft);
|
||||
|
||||
segment.LinkedTitle.Color = segment.LinkedTitle.HoverColor = segment.LinkedTitle.PressedColor = segment.LinkedTitle.SelectedColor = Color.Transparent;
|
||||
segment.LinkedText.Color = segment.LinkedText.HoverColor = segment.LinkedText.PressedColor = segment.LinkedText.SelectedColor = Color.Transparent;
|
||||
segment.ReplayButton.Color = segment.ReplayButton.HoverColor = segment.ReplayButton.PressedColor = segment.ReplayButton.SelectedColor = Color.Transparent;
|
||||
}
|
||||
|
||||
private void ReplaySegmentVideo(TutorialSegment segment)
|
||||
private void ReplaySegmentVideo(Segment segment)
|
||||
{
|
||||
if (ContentRunning) return;
|
||||
Inventory.DraggingItems.Clear();
|
||||
@@ -413,30 +348,31 @@ namespace Barotrauma.Tutorials
|
||||
//videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, callback: () => ContentRunning = false);
|
||||
}
|
||||
|
||||
private void ShowSegmentText(TutorialSegment segment)
|
||||
private void ShowSegmentText(Segment segment)
|
||||
{
|
||||
if (ContentRunning) return;
|
||||
Inventory.DraggingItems.Clear();
|
||||
ContentRunning = true;
|
||||
|
||||
string tutorialText = TextManager.GetFormatted(segment.TextContent.GetAttributeString("tag", ""), true, segment.Args);
|
||||
LocalizedString tutorialText = TextManager.GetFormatted(segment.TextContent.Value.Tag, segment.Args);
|
||||
|
||||
Action videoAction = null;
|
||||
|
||||
if (segment.ContentType != TutorialContentTypes.TextOnly)
|
||||
if (segment.ContentType != TutorialContentType.TextOnly)
|
||||
{
|
||||
videoAction = () => LoadVideo(segment);
|
||||
}
|
||||
|
||||
infoBox = CreateInfoFrame(TextManager.Get(segment.Id), tutorialText,
|
||||
segment.TextContent.GetAttributeInt("width", 300),
|
||||
segment.TextContent.GetAttributeInt("height", 80),
|
||||
segment.TextContent.GetAttributeString("anchor", "Center"), true, () => ContentRunning = false, videoAction);
|
||||
segment.TextContent.Value.Width,
|
||||
segment.TextContent.Value.Height,
|
||||
segment.TextContent.Value.Anchor, true, () => ContentRunning = false, videoAction);
|
||||
}
|
||||
|
||||
protected void RemoveCompletedObjective(TutorialSegment segment)
|
||||
protected void RemoveCompletedObjective(Index segmentIndex)
|
||||
{
|
||||
if (!HasObjective(segment)) return;
|
||||
if (!HasObjective(segmentIndex)) return;
|
||||
var segment = segments[segmentIndex];
|
||||
segment.IsTriggered = true;
|
||||
segment.ReplayButton.OnClicked = null;
|
||||
|
||||
@@ -467,18 +403,20 @@ namespace Barotrauma.Tutorials
|
||||
GUIImage stroke = new GUIImage(rectTB, "Stroke");
|
||||
stroke.Color = stroke.SelectedColor = stroke.HoverColor = stroke.PressedColor = color;
|
||||
|
||||
CoroutineManager.StartCoroutine(WaitForObjectiveEnd(segment));
|
||||
CoroutineManager.StartCoroutine(WaitForObjectiveEnd(segmentIndex));
|
||||
}
|
||||
|
||||
private IEnumerable<CoroutineStatus> WaitForObjectiveEnd(TutorialSegment objective)
|
||||
private IEnumerable<CoroutineStatus> WaitForObjectiveEnd(Index objectiveIndex)
|
||||
{
|
||||
var objective = segments[objectiveIndex];
|
||||
yield return new WaitForSeconds(2.0f);
|
||||
objectiveFrame.RemoveChild(objective.ReplayButton);
|
||||
activeObjectives.Remove(objective);
|
||||
activeObjectives.Remove(objectiveIndex);
|
||||
|
||||
for (int i = 0; i < activeObjectives.Count; i++)
|
||||
{
|
||||
activeObjectives[i].ReplayButton.RectTransform.AbsoluteOffset = new Point(0, (activeObjectives[i].ReplayButton.Rect.Height + 20) * i);
|
||||
var activeObjective = segments[activeObjectives[i]];
|
||||
activeObjective.ReplayButton.RectTransform.AbsoluteOffset = new Point(0, (activeObjective.ReplayButton.Rect.Height + 20) * i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,32 +430,25 @@ namespace Barotrauma.Tutorials
|
||||
return true;
|
||||
}
|
||||
|
||||
protected GUIComponent CreateInfoFrame(string title, string text, int width = 300, int height = 80, string anchorStr = "", bool hasButton = false, Action callback = null, Action showVideo = null)
|
||||
protected GUIComponent CreateInfoFrame(LocalizedString title, LocalizedString text, int width = 300, int height = 80, Anchor anchor = Anchor.TopRight, bool hasButton = false, Action callback = null, Action showVideo = null)
|
||||
{
|
||||
if (hasButton) height += 60;
|
||||
|
||||
Anchor anchor = Anchor.TopRight;
|
||||
|
||||
if (anchorStr != string.Empty)
|
||||
{
|
||||
Enum.TryParse(anchorStr, out anchor);
|
||||
}
|
||||
|
||||
width = (int)(width * GUI.Scale);
|
||||
height = (int)(height * GUI.Scale);
|
||||
|
||||
string wrappedText = ToolBox.WrapText(text, width, GUI.Font);
|
||||
height += (int)GUI.Font.MeasureString(wrappedText).Y;
|
||||
LocalizedString wrappedText = ToolBox.WrapText(text, width, GUIStyle.Font);
|
||||
height += (int)GUIStyle.Font.MeasureString(wrappedText).Y;
|
||||
|
||||
if (title.Length > 0)
|
||||
{
|
||||
height += (int)GUI.Font.MeasureString(title).Y + (int)(150 * GUI.Scale);
|
||||
height += (int)GUIStyle.Font.MeasureString(title).Y + (int)(150 * GUI.Scale);
|
||||
}
|
||||
|
||||
var background = new GUIFrame(new RectTransform(new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight), GUI.Canvas, Anchor.Center), style: "GUIBackgroundBlocker");
|
||||
|
||||
var infoBlock = new GUIFrame(new RectTransform(new Point(width, height), background.RectTransform, anchor));
|
||||
infoBlock.Flash(GUI.Style.Green);
|
||||
infoBlock.Flash(GUIStyle.Green);
|
||||
|
||||
var infoContent = new GUILayoutGroup(new RectTransform(new Vector2(0.9f, 0.9f), infoBlock.RectTransform, Anchor.Center))
|
||||
{
|
||||
@@ -528,20 +459,12 @@ namespace Barotrauma.Tutorials
|
||||
if (title.Length > 0)
|
||||
{
|
||||
var titleBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform),
|
||||
title, font: GUI.LargeFont, textAlignment: Alignment.Center, textColor: new Color(253, 174, 0));
|
||||
title, font: GUIStyle.LargeFont, textAlignment: Alignment.Center, textColor: new Color(253, 174, 0));
|
||||
titleBlock.RectTransform.IsFixedSize = true;
|
||||
}
|
||||
|
||||
List<RichTextData> richTextData = RichTextData.GetRichTextData(" " + text, out text);
|
||||
GUITextBlock textBlock;
|
||||
if (richTextData == null)
|
||||
{
|
||||
textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), text, wrap: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), richTextData, text, wrap: true);
|
||||
}
|
||||
text = RichString.Rich(text);
|
||||
GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), infoContent.RectTransform), text, wrap: true);
|
||||
|
||||
textBlock.RectTransform.IsFixedSize = true;
|
||||
infoBoxClosedCallback = callback;
|
||||
@@ -589,22 +512,26 @@ namespace Barotrauma.Tutorials
|
||||
#endregion
|
||||
|
||||
#region Video
|
||||
protected void LoadVideo(TutorialSegment segment)
|
||||
protected void LoadVideo(Segment segment)
|
||||
{
|
||||
if (videoPlayer == null) videoPlayer = new VideoPlayer();
|
||||
if (segment.ContentType != TutorialContentTypes.ManualVideo)
|
||||
if (segment.ContentType != TutorialContentType.ManualVideo)
|
||||
{
|
||||
videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), new VideoPlayer.TextSettings(segment.VideoContent), segment.Id, true, segment.Objective, StopCurrentContentSegment);
|
||||
videoPlayer.LoadContent(
|
||||
PlayableContentPath,
|
||||
new VideoPlayer.VideoSettings(segment.VideoContent.Value.File),
|
||||
new VideoPlayer.TextSettings(segment.VideoContent.Value.TextTag, segment.VideoContent.Value.Width),
|
||||
segment.Id, true, segment.Objective, StopCurrentContentSegment);
|
||||
}
|
||||
else
|
||||
{
|
||||
videoPlayer.LoadContent(playableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent), null, segment.Id, true, string.Empty, null);
|
||||
videoPlayer.LoadContent(PlayableContentPath, new VideoPlayer.VideoSettings(segment.VideoContent.Value.File), null, segment.Id, true, string.Empty, null);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Highlights
|
||||
protected void HighlightInventorySlot(Inventory inventory, string identifier, Color color, float fadeInDuration, float fadeOutDuration, float scaleUpAmount)
|
||||
protected void HighlightInventorySlot(Inventory inventory, Identifier identifier, Color color, float fadeInDuration, float fadeOutDuration, float scaleUpAmount)
|
||||
{
|
||||
if (inventory.visualSlots == null) { return; }
|
||||
for (int i = 0; i < inventory.Capacity; i++)
|
||||
@@ -616,7 +543,7 @@ namespace Barotrauma.Tutorials
|
||||
}
|
||||
}
|
||||
|
||||
protected void HighlightInventorySlotWithTag(Inventory inventory, string tag, Color color, float fadeInDuration, float fadeOutDuration, float scaleUpAmount)
|
||||
protected void HighlightInventorySlotWithTag(Inventory inventory, Identifier tag, Color color, float fadeInDuration, float fadeOutDuration, float scaleUpAmount)
|
||||
{
|
||||
if (inventory.visualSlots == null) { return; }
|
||||
for (int i = 0; i < inventory.Capacity; i++)
|
||||
|
||||
-6
@@ -5,11 +5,6 @@ namespace Barotrauma
|
||||
class TutorialMode : GameMode
|
||||
{
|
||||
public Tutorial Tutorial;
|
||||
|
||||
public static void StartTutorial(Tutorial tutorial)
|
||||
{
|
||||
tutorial.Initialize();
|
||||
}
|
||||
|
||||
public TutorialMode(GameModePreset preset)
|
||||
: base(preset)
|
||||
@@ -20,7 +15,6 @@ namespace Barotrauma
|
||||
{
|
||||
base.Start();
|
||||
GameMain.GameSession.CrewManager = new CrewManager(true);
|
||||
Tutorial.Start();
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
//don't consider the items to belong in the outpost to prevent the stealing icon from showing
|
||||
|
||||
Reference in New Issue
Block a user