This commit is contained in:
Regalis
2015-07-31 21:05:55 +03:00
parent 23d847a4ac
commit 85b0cda4ca
181 changed files with 4455 additions and 4073 deletions
+61
View File
@@ -0,0 +1,61 @@
using System.Xml.Linq;
using Microsoft.Xna.Framework;
using System;
namespace Subsurface
{
class MonsterEvent : ScriptedEvent
{
private string characterFile;
private int minAmount, maxAmount;
private Character[] monsters;
public MonsterEvent(XElement element)
: base (element)
{
characterFile = ToolBox.GetAttributeString(element, "characterfile", "");
minAmount = ToolBox.GetAttributeInt(element, "minamount", 1);
maxAmount = Math.Max(ToolBox.GetAttributeInt(element, "maxamount", 1),minAmount);
}
protected override void Start()
{
WayPoint randomWayPoint = WayPoint.GetRandom(SpawnType.Enemy);
int amount = Rand.Range(minAmount, maxAmount, false);
monsters = new Character[amount];
for (int i = 0; i < amount; i++)
{
Vector2 position = (randomWayPoint == null) ? Vector2.Zero : randomWayPoint.SimPosition;
position.X += Rand.Range(-0.5f, 0.5f);
position.Y += Rand.Range(-0.5f, 0.5f);
monsters[i] = new Character(characterFile, position);
}
}
public override void Update(float deltaTime)
{
base.Update(deltaTime);
if (!isStarted) return;
if (!isFinished)
{
bool monstersDead = true;
for (int i = 0; i < monsters.Length; i++)
{
if (monsters[i].IsDead) continue;
monstersDead = false;
break;
}
if (monstersDead) Finished();
}
}
}
}
+30
View File
@@ -0,0 +1,30 @@
namespace Subsurface
{
class PropertyTask : Task
{
Item item;
public delegate bool IsFinishedHandler();
private IsFinishedHandler IsFinishedChecker;
public PropertyTask(Item item, IsFinishedHandler isFinished, float priority, string name)
: base(priority, name)
{
if (taskManager == null) return;
this.item = item;
IsFinishedChecker = isFinished;
taskManager.TaskStarted(this);
}
public override void Update(float deltaTime)
{
if (IsFinishedChecker())
{
Finished();
}
}
}
}
@@ -0,0 +1,53 @@
using FarseerPhysics;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Subsurface
{
class MonsterQuest : Quest
{
//string monsterName;
string monsterFile;
Character monster;
public override Vector2 RadarPosition
{
get
{
return monster.Position;
}
}
public MonsterQuest(XElement element)
: base(element)
{
monsterFile = ToolBox.GetAttributeString(element, "monsterfile", "");
}
public override void Start(Level level)
{
Vector2 position = level.PositionsOfInterest[Rand.Int(level.PositionsOfInterest.Count)];
monster = new Character(monsterFile, ConvertUnits.ToSimUnits(position+level.Position));
}
public override void End()
{
if (!monster.IsDead)
{
new GUIMessageBox("Quest failed", failureMessage);
return;
}
GiveReward();
completed = true;
}
}
}
+171
View File
@@ -0,0 +1,171 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml.Linq;
namespace Subsurface
{
class Quest
{
private static List<Quest> list = new List<Quest>();
private static string configFile = "Content/Quests.xml";
private string name;
private string description;
protected bool completed;
protected string successMessage;
protected string failureMessage;
protected string radarLabel;
private int reward;
public string Name
{
get { return name; }
}
public string Description
{
get { return description; }
}
public int Reward
{
get { return reward; }
}
public bool Completed
{
get { return completed; }
}
public virtual string RadarLabel
{
get { return radarLabel; }
}
public virtual Vector2 RadarPosition
{
get { return Vector2.Zero; }
}
public Quest(XElement element)
{
name = ToolBox.GetAttributeString(element, "name", "");
description = ToolBox.GetAttributeString(element, "description", "");
reward = ToolBox.GetAttributeInt(element, "reward", 1);
successMessage = ToolBox.GetAttributeString(element, "successmessage", "");
failureMessage = ToolBox.GetAttributeString(element, "failuremessage", "");
radarLabel = ToolBox.GetAttributeString(element, "radarlabel", "");
}
public static Quest LoadRandom(Location[] locations, Random rand)
{
XDocument doc = ToolBox.TryLoadXml(configFile);
if (doc == null) return null;
int eventCount = doc.Root.Elements().Count();
//int[] commonness = new int[eventCount];
float[] eventProbability = new float[eventCount];
float probabilitySum = 0.0f;
int i = 0;
foreach (XElement element in doc.Root.Elements())
{
eventProbability[i] = ToolBox.GetAttributeInt(element, "commonness", 1);
probabilitySum += eventProbability[i];
i++;
}
float randomNumber = (float)rand.NextDouble() * probabilitySum;
i = 0;
foreach (XElement element in doc.Root.Elements())
{
if (randomNumber <= eventProbability[i])
{
Type t;
string type = element.Name.ToString();
try
{
t = Type.GetType("Subsurface." + type + ", Subsurface", true, true);
if (t == null)
{
DebugConsole.ThrowError("Error in " + configFile + "! Could not find a quest class of the type ''" + type + "''.");
continue;
}
}
catch
{
DebugConsole.ThrowError("Error in " + configFile + "! Could not find a an event class of the type ''" + type + "''.");
continue;
}
ConstructorInfo constructor = t.GetConstructor(new[] { typeof(XElement) });
object instance = constructor.Invoke(new object[] { element });
Quest quest = (Quest)instance;
for (int n = 0; n<2; n++)
{
quest.description = quest.description.Replace("[location"+(n+1)+"]", locations[n].Name);
quest.successMessage = quest.successMessage.Replace("[location" + (n + 1) + "]", locations[n].Name);
quest.failureMessage = quest.failureMessage.Replace("[location" + (n + 1) + "]", locations[n].Name);
}
return quest;
}
randomNumber -= eventProbability[i];
i++;
}
return null;
}
public virtual void Start(Level level)
{
}
/// <summary>
/// End the quest and give a reward if it was completed successfully
/// </summary>
/// <returns>whether the quest was completed or not</returns>
public virtual void End()
{
completed = true;
GiveReward();
}
public void GiveReward()
{
var mode = Game1.GameSession.gameMode as SinglePlayerMode;
mode.Money += reward;
if (!string.IsNullOrWhiteSpace(successMessage))
{
new GUIMessageBox("Quest completed", successMessage);
}
}
}
}
@@ -0,0 +1,59 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace Subsurface
{
class SalvageQuest : Quest
{
ItemPrefab itemPrefab;
Item item;
public override Vector2 RadarPosition
{
get
{
return item.Position;
}
}
public SalvageQuest(XElement element)
: base(element)
{
string itemName = ToolBox.GetAttributeString(element, "itemname", "");
itemPrefab = ItemPrefab.list.Find(ip => ip.Name == itemName) as ItemPrefab;
if (itemPrefab == null)
{
DebugConsole.ThrowError("Error in salvagequest: couldn't find an item prefab with the name "+itemName);
}
}
public override void Start(Level level)
{
Vector2 position = level.PositionsOfInterest[Rand.Int(level.PositionsOfInterest.Count)];
item = new Item(itemPrefab, position + level.Position);
//item.MoveWithLevel = true;
}
public override void End()
{
if (item.CurrentHull == null)
{
new GUIMessageBox("Quest failed", failureMessage);
return;
}
item.Remove();
GiveReward();
completed = true;
}
}
}
+22
View File
@@ -0,0 +1,22 @@
namespace Subsurface
{
class RepairTask : Task
{
Item item;
public RepairTask(Item item, float priority, string name)
: base(priority, name)
{
if (taskManager == null) return;
this.item = item;
taskManager.TaskStarted(this);
}
public override void Update(float deltaTime)
{
if (item.Condition > 50.0f) Finished();
}
}
}
+202
View File
@@ -0,0 +1,202 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
namespace Subsurface
{
class ScriptedEvent
{
private static string configFile = "Content/randomevents.xml";
const int MaxPreviousEvents = 6;
const float PreviouslyUsedWeight = 10.0f;
static List<int> previousEvents = new List<int>();
protected string name;
protected string description;
protected int commonness;
protected int difficulty;
//the time after starting a shift after which the event is started
//the time is set to a random value between startTimeMin and startTimeMax at the start of the shift
private int startTimeMin;
private int startTimeMax;
private double startTimer;
protected bool isStarted;
protected bool isFinished;
public string Name
{
get { return name; }
}
public string Description
{
get { return description; }
}
public int Commonness
{
get { return commonness; }
}
public string MusicType
{
get;
set;
}
public bool IsStarted
{
get { return isStarted; }
}
public bool IsFinished
{
get { return isFinished; }
}
public int Difficulty
{
get { return difficulty; }
}
public ScriptedEvent(XElement element)
{
name = ToolBox.GetAttributeString(element, "name", "");
description = ToolBox.GetAttributeString(element, "description", "");
difficulty = ToolBox.GetAttributeInt(element, "difficulty", 1);
commonness = ToolBox.GetAttributeInt(element, "commonness", 1);
MusicType = ToolBox.GetAttributeString(element, "musictype", "default");
if (element.Attribute("starttime") != null)
{
startTimeMax = ToolBox.GetAttributeInt(element, "starttime", 1);
startTimeMin = startTimeMax;
}
else
{
startTimeMax = ToolBox.GetAttributeInt(element, "starttimemax", 1);
startTimeMin = ToolBox.GetAttributeInt(element, "starttimemin", 1);
}
}
public static ScriptedEvent LoadRandom(Random rand)
{
XDocument doc = ToolBox.TryLoadXml(configFile);
if (doc == null) return null;
int eventCount = doc.Root.Elements().Count();
//int[] commonness = new int[eventCount];
float[] eventProbability = new float[eventCount];
float probabilitySum = 0.0f;
int i = 0;
foreach (XElement element in doc.Root.Elements())
{
eventProbability[i] = ToolBox.GetAttributeInt(element, "commonness", 1);
//if the event has been previously selected, it's less likely to be selected now
int previousEventIndex = previousEvents.FindIndex(x => x == i);
if (previousEventIndex >= 0)
{
//how many shifts ago was the event last selected
int eventDist = eventCount - previousEventIndex;
float weighting = (1.0f / eventDist) * PreviouslyUsedWeight;
eventProbability[i] *= weighting;
}
probabilitySum += eventProbability[i];
i++;
}
float randomNumber = (float)rand.NextDouble() * probabilitySum;
i = 0;
foreach (XElement element in doc.Root.Elements())
{
if (randomNumber <= eventProbability[i])
{
Type t;
string type = element.Name.ToString();
try
{
t = Type.GetType("Subsurface." + type + ", Subsurface", true, true);
if (t == null)
{
DebugConsole.ThrowError("Error in " + configFile + "! Could not find an event class of the type ''" + type + "''.");
continue;
}
}
catch
{
DebugConsole.ThrowError("Error in " + configFile + "! Could not find an event class of the type ''" + type + "''.");
continue;
}
ConstructorInfo constructor = t.GetConstructor(new[] { typeof(XElement) });
object instance = constructor.Invoke(new object[] { element });
previousEvents.Add(i);
return (ScriptedEvent)instance;
}
randomNumber -= eventProbability[i];
i++;
}
return null;
}
public virtual void Init()
{
isStarted = false;
isFinished = false;
startTimer = Rand.Range(startTimeMin, startTimeMax, false);
}
protected virtual void Start()
{
}
public virtual void Update(float deltaTime)
{
if (isStarted) return;
if (startTimer>0)
{
startTimer -= deltaTime;
}
else
{
Start();
isStarted = true;
}
}
public virtual void Finished()
{
isFinished = true;
//EventManager.EventFinished(this);
}
}
}
+32
View File
@@ -0,0 +1,32 @@
namespace Subsurface
{
class ScriptedTask : Task
{
private ScriptedEvent scriptedEvent;
private bool prevStarted;
public ScriptedTask(ScriptedEvent scriptedEvent)
: base(scriptedEvent.Difficulty, scriptedEvent.Name)
{
if (taskManager == null) return;
this.musicType = scriptedEvent.MusicType;
this.scriptedEvent = scriptedEvent;
scriptedEvent.Init();
}
public override void Update(float deltaTime)
{
if (prevStarted == false && scriptedEvent.IsStarted)
{
taskManager.TaskStarted(this);
prevStarted = true;
}
scriptedEvent.Update(deltaTime);
if (scriptedEvent.IsFinished) Finished();
}
}
}
+60
View File
@@ -0,0 +1,60 @@
namespace Subsurface
{
class Task
{
protected string name;
private float priority;
protected string musicType;
protected TaskManager taskManager;
protected bool isFinished;
public string Name
{
get { return name; }
}
public float Priority
{
get { return priority; }
}
public string MusicType
{
get { return musicType; }
}
public bool IsFinished
{
get { return isFinished; }
}
public Task(float priority, string name)
{
if (Game1.GameSession==null || Game1.GameSession.taskManager == null) return;
taskManager = Game1.GameSession.taskManager;
musicType = "repair";
this.priority = priority;
this.name = name;
taskManager.AddTask(this);
}
public virtual void Update(float deltaTime)
{
}
protected virtual void Finished()
{
taskManager.TaskFinished(this);
isFinished = true;
}
}
}
+163
View File
@@ -0,0 +1,163 @@
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
namespace Subsurface
{
class TaskManager
{
const float CriticalPriority = 50.0f;
private List<Task> tasks;
private GUIListBox taskListBox;
public List<Task> Tasks
{
get { return tasks; }
}
public bool CriticalTasks
{
get
{
foreach (Task task in tasks)
{
if (task.Priority >= CriticalPriority) return true;
}
return false;
}
}
public TaskManager(GameSession session)
{
tasks = new List<Task>();
taskListBox = new GUIListBox(new Rectangle(Game1.GraphicsWidth - 250, 50, 250, 500), Color.Transparent);
//taskListBox.ScrollBarEnabled = false;
//taskListBox.Padding = GUI.style.smallPadding;
}
public void AddTask(Task newTask)
{
if (tasks.Contains(newTask)) return;
tasks.Add(newTask);
}
public void StartShift(Level level)
{
CreateScriptedEvents(level);
taskListBox.ClearChildren();
}
public void EndShift()
{
taskListBox.ClearChildren();
tasks.Clear();
}
private void CreateScriptedEvents(Level level)
{
Random rand = new Random(level.Seed.GetHashCode());
float totalDifficulty = level.Difficulty;
int tries = 0;
do
{
ScriptedEvent scriptedEvent = ScriptedEvent.LoadRandom(rand);
if (scriptedEvent==null || scriptedEvent.Difficulty > totalDifficulty)
{
tries++;
continue;
}
AddTask(new ScriptedTask(scriptedEvent));
totalDifficulty -= scriptedEvent.Difficulty;
tries = 0;
} while (tries < 5);
}
public void TaskStarted(Task task)
{
Color color = Color.Red;
int width = 250;
if (task.Priority < 30.0f)
{
width = 200;
color = Color.Yellow;
}
else if (task.Priority < 60)
{
width = 220;
color = Color.Orange;
}
GUIFrame frame = new GUIFrame(new Rectangle(0,0,width,40), Color.Transparent, Alignment.Right, null, taskListBox);
frame.UserData = task;
frame.Padding = new Vector4(0.0f, 5.0f, 5.0f, 5.0f);
GUIFrame colorFrame = new GUIFrame(new Rectangle(0, 0, 0, 0), color * 0.5f, Alignment.Right, null, frame);
GUITextBlock textBlock = new GUITextBlock(new Rectangle(5, 5, 0, 20), task.Name, Color.Transparent, Color.Black, Alignment.Right, null, colorFrame);
//textBlock.Padding = new Vector4(10.0f, 10.0f, 0.0f, 0.0f);
//colorFrame.AddChild(textBlock);
taskListBox.children.Sort((x, y) => ((Task)y.UserData).Priority.CompareTo(((Task)x.UserData).Priority));
}
public void TaskFinished(Task task)
{
}
public void Update(float deltaTime)
{
Task removeTask = null;
GUIComponent removeComponent = null;
foreach (Task task in tasks)
{
if (task.IsFinished)
{
foreach (GUIComponent comp in taskListBox.children)
{
if (comp.UserData as Task != task) continue;
comp.Rect = new Rectangle(comp.Rect.X, comp.Rect.Y, comp.Rect.Width, comp.Rect.Height - 1);
comp.children[0].ClearChildren();
if (comp.Rect.Height < 1)
{
removeComponent = comp;
removeTask = task;
}
break;
}
}
else
{
task.Update(deltaTime);
}
}
if (removeComponent!= null)
{
taskListBox.RemoveChild(removeComponent);
tasks.Remove(removeTask);
}
//endShiftButton.Enabled = finished || Game1.server!=null;
}
public void Draw(SpriteBatch spriteBatch)
{
taskListBox.Draw(spriteBatch);
}
}
}